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",
],
},
}
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
There is a closed issue about this in the react-hook-form github https://github.com/react-hook-form/react-hook-form/issues/1781