reactjsreact-hook-formreact-forms

Validating an optional Field With React Hook Form


I'm working on a form with some optional fields that need to be validated only if an input is entered. However, react hook form returns a validation error even when no inputs. I have also tried to set:

required: {
value: false,
message: "This field is not required"
}

But it still returns a validation error even when no inputs are entered.

Below is the code snippets for one of the fields that need to be validated only if an input is entered.

<div className={styles.formInputFile}>
          <label htmlFor="ref_letter">
            Reference Letter (For Doctorate and Diploma Courses)
          </label>
          <Controller
            control={control}
            name={"reference_letter"}
            rules={{
            required: {
              value: refLetterRequired();
              message: "This is field is required",
},
              validate: {
                fileSize: (file) => {
                  return (
                    file?.size < 2000100 &&
                    "File size shouldn't be more than 2MB!"
                  );
                },
                acceptedFormats: (file) => {
                  return (
                    ["image/png", "image/jpeg", "application/pdf"].includes(
                      file?.type
                    ) || "Only JPEG, PNG and PDF files are accepted!"
                  );
                },
              },
            }}
            render={({ field: { value, onChange, ...field } }) => {
              return (
                <input
                  {...field}
                  value={value?.fileName}
                  onChange={(event) => {
                    onChange(event.target.files[0]);
                  }}
                  type="file"
                  id="rererence_letter"
                  accept=".png, .jpeg, .pdf"
                />
              );
            }}
          />
          <p>{errors.reference_letter?.message}</p>
        </div>

Second Edit:

The form is a multi-step form and each step needs to be free of errors before users can move to the next step. Below are all the code snippets controlling the field. I keep getting validation errors even when the right inputs are there and when the field is not required.

  const certCourses = [
    "Certificate in D",
    "Certificate in t",
    "certificate in H",
    "Certificate in P",
    "Certificate in Pus",
    "Certificate Hec Diseases",
    "Certificate in He",
  ];

  const refLetterRequired = () => {
    for (let i = 0; i < certCourses.length; i++) {
      if (watch("proposed_course") === certCourses[i]) return false;
    }
    return true;
  };

Expectations. If the "proposed_course" selected is not in "certCourses", then the field should be required, otherwise, the field should not be required.

Code controlling "next" button of the multi-step form:

  const next = async (e) => {
    const field = steps[currentStep].fields;
    const output = await trigger(field);
    if (!output) return;
    setValue(e.target.name, e.target.value, {
      shouldDirty: true,
      shouldValidate: true,
      shouldTouch: true,
    });
    setCurrentStep(currentStep + 1);
  };

const [currentStep, setCurrentStep] = useState(0);




const steps = [
  {
    name: "step 1",
    description: "Personal Information",
    fields: [
      "title",
      "surname",
      "first_name",
      "gender",
      "middle_name",
      "maiden_name",
      "religion",
      "birth_date",
      "nationality",
      "state_of_origin",
      "disability",
    ],
  },
  {
    name: "step 2",
    description: "Next of Kin Information",
    fields: [
      "next_of_kin_name",
      "next_of_kin_address",
      "next_of_kin_relationship",
      "next_of_kin_phone",
      "next_of_kin_occupation",
    ],
  },
}

Solution

  • You can check if the field value is empty or equal to the default value and return "true"(i.e. indicate that the field passed validation) in that case.
    For example

    fileSize: (file) => {
      if (file === null) return true;
      return (
        file?.size < 2000100 &&
        "File size shouldn't be more than 2MB!"
       );
    },
    

    There is a closed issue about this in the react-hook-form github https://github.com/react-hook-form/react-hook-form/issues/1781