Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nullable date should not parse as invalid date in v1.0.2 #1952

Closed
exah opened this issue Mar 17, 2023 · 9 comments
Closed

Nullable date should not parse as invalid date in v1.0.2 #1952

exah opened this issue Mar 17, 2023 · 9 comments

Comments

@exah
Copy link

exah commented Mar 17, 2023

Describe the bug

Yup.date().nullable().required('Required') produces invalid date error when initial value is null:

key must be a `date` type, but the final value was: `Invalid Date`

To Reproduce

https://codesandbox.io/s/cool-swartz-b4pfbp?file=/src/index.test.js

Expected behavior

Should return ValidationError with 'Required' message.

Platform (please complete the following information):

  • Firefox
  • 111

Additional context

Stopped working in v1.0.2.

Temporary solution is to replace yup.date() with yup.mixed((val): val is Date => val instanceof Date), but min, max methods needs to be re-implemented as well.

@jquense
Copy link
Owner

jquense commented Mar 17, 2023

its not nullable in your example, you Yup.date().nullable().required('Required') the required overrides the nullable, this is a change in v1, see #1906

@jquense jquense closed this as completed Mar 17, 2023
@exah
Copy link
Author

exah commented Mar 17, 2023

Hey @jquense, thanks for the reply.

I understood that. I need to remove .nullable() as .required() already checks it for me, but I have one follow-up question.

Even if I remove nullable and use just required(), I get the same invalid date error:

https://codesandbox.io/s/bold-zeh-2btd0d?file=/src/index.test.js

Although if I replace .date() with .mixed(), everything works as expected because there is no parsing happens during the validation (expected behaviour for me):

https://codesandbox.io/s/jovial-phoebe-63sidy?file=/src/index.test.js

Should I switch to .mixed in my case?

@bel0v
Copy link

bel0v commented Mar 17, 2023

@jquense hi, the issue stays with Yup.date().required('Required')

https://codesandbox.io/s/weathered-worker-xw3tov?file=/src/index.test.js:100-131

so it seems to be a bug related to date() casting, not the nullable override you mentioned

@jquense
Copy link
Owner

jquense commented Mar 17, 2023

it works if the date is actually nullable date().nullable().cast(null)

@jarnaiz
Copy link

jarnaiz commented Apr 13, 2023

Hello,

I dont understand the new API:

it("required string pass", async () => {
  await expect(
    yup.string().required("Required").validate(null)
  ).rejects.toEqual(new yup.ValidationError("Required"));
});

it("required date fails", async () => {
  await expect(
    yup.date().required("Required").validate(null)
  ).rejects.toEqual(new yup.ValidationError("Required"));
});

it("required date pass", async () => {
  await expect(
    yup.date().required().typeError("Required").validate(null)
  ).rejects.toEqual(new yup.ValidationError("Required"));
});

I think the first and the second test should behave the same way.

https://codesandbox.io/s/gracious-wind-g7l4nl?file=/src/index.test.js:29-537

@jquense
Copy link
Owner

jquense commented Apr 13, 2023

Ah yes those should be the same, seems like there is a bug

@jarnaiz
Copy link

jarnaiz commented Apr 14, 2023

Maybe we must reopen this issue? Thanks!

@jquense
Copy link
Owner

jquense commented Apr 14, 2023

This issue isn't about that,you can open a new one tho if you want 👍

@rodfagui
Copy link

rodfagui commented Feb 21, 2024

I had a similar problem in my nextJS application using RHF, yup and material ui datepicker v6. I resolved the issue in the following way

This is my yup schema

export const editVehicleFormSchema = yup.object().shape({
  plate: yup
    .string()
    .typeError("La placa debe ser un cadena de caracteres")
    .required("La placa es requerida"),
  brand: yup
    .string()
    .typeError("La marca debe ser un cadena de caracteres")
    .required("La marca es requerida"),
  color: yup
    .string()
    .typeError("El color debe ser un cadena de caracteres")
    .required("El color es requerido"),
  numberOfDoors: yup
    .number()
    .integer()
    .positive()
    .typeError("El número de puertas debe ser un entero positivo")
    .required("El número de puertas es requerido"),
  armor: yup
    .boolean()
    .typeError("El blindaje debe ser verdadero o falso")
    .required("EL blindaje es requerido"),
  registeredAt: yup
    .date()
    .typeError("La fecha de matricula no tiene un formato válido")
    .required("La fecha de matricula es requerida"),
});

And this is my useForm declaration

const {
    control: editVehicleFormControl,
    formState: {
      errors: editVehicleFormErrors,
      isValid: editVehicleFormIsValid,
    },
    handleSubmit: handleEditVehicleFormSubmit,
    reset: editVehicleFormReset,
    setValue: editVehicleSetValue,
    watch: editVehicleFormWatch,
    getValues: editVehicleFormGetValues,
  } = useForm({
    defaultValues: {
      plate: "",
      brand: "",
      color: "",
      numberOfDoors: 2,
      armor: false,
      registeredAt: dayjs().toDate(),
    },
    resolver: yupResolver(editVehicleFormSchema),
    mode: "onBlur",
  });

With a TextField component like this I implemented the validations and showed the error as follows

<FormControl fullWidth sx={{ mb: 4 }}>
  <Controller
   name="color"
   control={editVehicleFormControl}
   rules={{ required: true }}
   render={({ field: { value, onChange, onBlur } }) => (
     <TextField
        label="Color"
        value={value}
        onBlur={onBlur}
        onChange={onChange}
        error={Boolean(editVehicleFormErrors.color)}
      />
   )}
  />
  {editVehicleFormErrors.color && (
  <FormHelperText sx={{ color: "error.main" }} id="">
    {editVehicleFormErrors.color.message}
  </FormHelperText>
  )}
</FormControl>

And with a date picker component I did it like this

<FormControl fullWidth sx={{ mb: 4 }}>
  <Controller
     name="registeredAt"
     control={editVehicleFormControl}
     rules={{ required: true }}
     render={({ field: { value } }) => {
       return (
         <LocalizationProvider dateAdapter={AdapterDayjs}>
            <DatePicker
               label="Fecha de matricula"
               value={dayjs(value)}
               slotProps={{
                 textField: {
                   error: Boolean(editVehicleFormErrors.registeredAt),
                 },
               }}
               onChange={(newValue) => {
                  if (newValue && dayjs(newValue).isValid()) {
                    editVehicleSetValue(
                      "registeredAt",
                      dayjs(newValue).toDate(),
                      { shouldValidate: true },
                    );
                  } else {
                    editVehicleSetValue(
                      "registeredAt",
                       null as unknown as Date,
                       {
                         shouldValidate: true,
                       },
                    );
                  }
               }}
            />
     </LocalizationProvider>
      );
    }}
   />
   {editVehicleFormErrors.registeredAt && (
     <FormHelperText sx={{ color: "error.main" }} id="">
        {editVehicleFormErrors.registeredAt.message}
     </FormHelperText>
    )}
</FormControl>

Sorry for the bad identation of my code. I hope I have been helpful

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants