You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中使用Formik与Yup实现条件表单验证时无法修改showfile值的问题

Fixing the showfile Value Update & Conditional Validation in Formik + Yup

Got it, let's break down why your showfile value isn't updating and get that conditional validation working properly.

First: The Root Cause of showfile Not Changing

Looking at your onChange handler for the file input:

onChange={(event) => formik.setFieldValue( "file", event.currentTarget.files[0], "showfile", true ) }

The setFieldValue method only accepts three arguments max: (fieldName: string, value: any, shouldValidate?: boolean). You're trying to pass two field-value pairs in one call, which doesn't work—Formik ignores the extra arguments, so showfile never gets set to true.

Step 1: Correctly Update Both file and showfile

You need to update the two fields separately. You can either call setFieldValue twice, or use setValues to update multiple fields at once:

Option 1: Call setFieldValue Twice

onChange={(event) => {
  const selectedFile = event.currentTarget.files[0];
  formik.setFieldValue("file", selectedFile);
  formik.setFieldValue("showfile", true); // Now this will actually update the value
}}

Option 2: Use setValues for Bulk Update

onChange={(event) => {
  const selectedFile = event.currentTarget.files[0];
  formik.setValues({
    ...formik.values,
    file: selectedFile,
    showfile: true
  });
}}

Also, fix the value prop on your TextField—you have formik.value which is a typo, it should be formik.values.file:

<TextField 
  label="Resume" 
  star="*" 
  color="red" 
  name="file" 
  type="file" 
  accept=".pdf,.docx,.doc" 
  onChange={/* corrected handler above */} 
  value={formik.values.file} 
/>

Step 2: Fix Yup Validation Rule Issues

Your Yup test has a syntax error—you're missing an && between the size check and format check. Also, you can simplify the when block since you don't need to re-declare Yup.mixed() in the then clause:

const SUPPORTED_FORMATS = ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"];
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB example

file: Yup.mixed().when("showfile", {
  is: true,
  then: (schema) => schema
    .required("Resume is required")
    .test(
      "FILE_SIZE",
      "Uploaded file is too big (max 5MB)",
      (value) => value && value.size <= MAX_FILE_SIZE
    )
    .test(
      "FILE_FORMAT",
      "Only PDF, DOC, DOCX files are allowed",
      (value) => value && SUPPORTED_FORMATS.includes(value.type)
    ),
})

Split the size and format checks into separate test methods for clarity (and so error messages are specific to each issue).

Step 3: Verify Initial Values

Your initial showfile value is set to false in Formik's initialValues, which is correct—this ensures validation only kicks in once a file is selected (and showfile becomes true).

Full Corrected Snippet Recap

Here's how the key parts should look together:

// Yup Validation
const SUPPORTED_FORMATS = ["application/pdf", "application/msword", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"];
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB example

const validate = Yup.object().shape({
  UserName: Yup.string().required("Username is required"),
  email: Yup.string().email("Invalid email").required("Email is required"),
  Phone: Yup.string().required("Phone number is required"),
  message: Yup.string().required("Message is required"),
  file: Yup.mixed().when("showfile", {
    is: true,
    then: (schema) => schema
      .required("Resume is required")
      .test(
        "FILE_SIZE",
        "Uploaded file is too big (max 5MB)",
        (value) => value && value.size <= MAX_FILE_SIZE
      )
      .test(
        "FILE_FORMAT",
        "Only PDF, DOC, DOCX files are allowed",
        (value) => value && SUPPORTED_FORMATS.includes(value.type)
    ),
  }),
});

// Formik Component
<Formik
  initialValues={{
    UserName: "",
    email: "",
    Phone: "",
    message: "",
    file: "",
    showfile: false,
    submit: false,
  }}
  validationSchema={validate}
  onSubmit={(values, actions) => {
    setTimeout(() => {
      console.log(values);
      actions.setSubmitting(false);
    }, 1000);
  }}
>
  {({ formik }) => (
    <TextField 
      label="Resume" 
      star="*" 
      color="red" 
      name="file" 
      type="file" 
      accept=".pdf,.docx,.doc" 
      onChange={(event) => {
        const selectedFile = event.currentTarget.files[0];
        formik.setFieldValue("file", selectedFile);
        formik.setFieldValue("showfile", true);
      }} 
      value={formik.values.file} 
    />
  )}
</Formik>

That should fix the showfile update issue and get your conditional validation working as expected!

内容的提问来源于stack exchange,提问作者shubham sourabh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 15:32:34