javascripthtmlreactjsvalidationyup

Optional field validation in Yup schema


I'm using react-hook-form with yup for my form validation and want some fields to be optional (null).

Following their documentation, I'm using nullable() and optional() but it is still getting validated:

export const updateAddressSchema = yup.object({
  address: yup
    .string()
    .nullable()
    .optional()
    .min(5, "Address must be more than 5 characters long")
    .max(255, "Address must be less than 255 characters long"),
  city: yup
    .string()
    .nullable()
    .optional()
    .max(32, "City name must be less than 32 characters long"),
  postal_code: yup
    .string()
    .nullable()
    .optional()
    .length(10, "Postal code must be 10 characters long"),
  phone: yup
    .string()
    .nullable()
    .optional()
    .min(10, "Phone number must be more than 10 characters long")
    .max(20, "Phone number must be less than 20 characters long"),
});

Is there any right way to do this?


Solution

  • Thanks a lot to @Usama for their answer and solution!

    I experienced another problem when using their solution. My back-end API disregards null values and returns the previous value if null values are submitted. The problem was that on initial render the text field's value was null but after selecting and typing and then deleting the typed letters to get it empty again (without submitting), its value would change to an empty string and so my API would throw an error and wouldn't update the user info.

    The way I managed to fix it was to use yup's .transform() method to transform the type from empty string to null if the text field wasn't filled:

    export const updateAddressSchema = yup.object().shape(
      {
        address: yup.string().when("address", (value) => {
          if (value) {
            return yup
              .string()
              .min(5, "Address must be more than 5 characters long")
              .max(255, "Address must be less than 255 characters long");
          } else {
            return yup
              .string()
              .transform((value, originalValue) => {
                // Convert empty values to null
                if (!value) {
                  return null;
                }
                return originalValue;
              })
              .nullable()
              .optional();
          }
        }),
        ......................
      },
      [
        ["address", "address"],
        ......................,
      ]
    );
    

    I really hope this helps someone.