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"
}
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>
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.
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",
],
},
}
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