conditional validation with yup and react hook form

26 views Asked by At

I have add questions form, and i have validating it using yup and react hook form but this error appear to me when just form rendered, here is error ( TypeError: Cannot read properties of undefined (reading 'reduce') ), and here is my yup schema

const schema = yup.object({
  questions: yup.array().of(
    yup.object().shape({
      subject: yup.string().required('subject is required'),
      subLevel: yup.string().required("sublevel is required"),
      difficultyLevel: yup.string().required("difficulty level is required"),
      type: yup.string().required("Answer type is required"),
      name: yup.string().required("Question is required"),
      image: yup.mixed()
        .test('fileType', 'Invalid file format', (value) => {
          if (!value || typeof value === 'string') return true;
          const supportedFormats = ['image/jpeg', 'image/png'];
          return supportedFormats.includes(value[0]?.type);
        }),
      correctOption: yup.string().when("type",{
        is: "MCQ",
        then: yup.string().required("You must enter at least one options"),
        otherwise: yup.string().notRequired(),
      }),
    })
  ),
})

I think that error because of the way of handle correctOption field , and I don't know if i am accessing the type field value inside when funtion in the correct way or not.

1

There are 1 answers

1
Khuong Viet Tai On

You can do this using yup.lazy() to dynamically define the schema based on the value of type. Here's how you can modify your schema

code

const schema = yup.object({
  questions: yup.array().of(
    yup.lazy((value) =>
      yup.object().shape({
        subject: yup.string().required('Subject is required'),
        subLevel: yup.string().required("Sublevel is required"),
        difficultyLevel: yup.string().required("Difficulty level is required"),
        type: yup.string().required("Answer type is required"),
        name: yup.string().required("Question is required"),
        image: yup.mixed().test('fileType', 'Invalid file format', (value) => {
          if (!value || typeof value === 'string') return true;
          const supportedFormats = ['image/jpeg', 'image/png'];
          return supportedFormats.includes(value[0]?.type);
        }),
        correctOption: yup.string().when("type", {
          is: "MCQ",
          then: yup.string().required("You must enter at least one option"),
          otherwise: yup.string().default('').notRequired(),
        }),
      })
    )
  ),
});