skip to Main Content

I have a DateTimePicker component that I’m trying to use in a form controlled by react-hook-form, the validation is really simple, using the disablePast prop on the DateTimePicker to ensure that the date selected is in the future.

The issue is that, for reasons unknown, the error does not persist through the value being changed, even if the new value is also invalid. For example:

  1. Select tomorrow’s date – no error (as it should be)
  2. Change the selected date to yesterday – disablePast error (as it should be)
  3. Change the selected date to the day before that – no error, but there should be

It also exhibits a similar behaviour when going back up, e.g:

  1. Enter in a date for two days ago – error (as it should be)
  2. Increase the date by one, so the value is yesterday – no error, but there should be
  3. Increase the date by one again, so the value is today – error, but there shouldn’t be

All of this is, of course, assuming that the time selected is after the current time, so "today" being selected is definitely not in the past.

I have a feeling that the ‘error state’ of the Mui component and react-hook-form are not in sync with each other, but I’m not sure how to fix it.

I’ve put together a codesandbox here, where the issue can be seen:

https://codesandbox.io/s/reverent-pare-yebckz?file=/src/App.js

And my code is also included here:

import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { useForm, useController } from "react-hook-form";
import { DateTimePicker } from "@mui/x-date-pickers/DateTimePicker"; // v6.0.4
import "dayjs/locale/en-gb";

const MyDateTimePicker = ({ name, control, error, setError }) => {
  const { field } = useController({ name, control });
  const handleError = (reason) => {
    console.log(reason);
    setError(name, {
      type: "custom",
      message: reason
    });
  };
  return (
    <DateTimePicker
      {...field}
      label="future date"
      disablePast
      onError={handleError}
      slotProps={{
        textField: {
          error: !!error,
          helperText: error?.message
        }
      }}
    />
  );
};

export default function App() {
  const {
    control,
    handleSubmit,
    setError,
    formState: { errors }
  } = useForm({
    mode: "all",
    defaultValues: {
      datetime: null
    }
  });

  const onSubmit = (data) => console.log(data);

  return (
    <LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale="en-gb">
      <div className="App">
        <form onSubmit={handleSubmit(onSubmit)}>
          <MyDateTimePicker
            name="datetime"
            control={control}
            error={errors?.datetime}
            setError={setError}
          />
        </form>
      </div>
    </LocalizationProvider>
  );
}

I feel like I’m losing my mind a little bit with this one, so any assistance would be greatly appreciated. Thank you

edit: It seems like setError is perhaps the problem. How, then, can I connect Mui’s validation to react-hook-form’s validation so they work together?

2

Answers


  1. Chosen as BEST ANSWER

    Fixed it by ditching setError entirely and writing my own validation as part of react-hook-form's rules.

    Working example: https://codesandbox.io/s/eloquent-kowalevski-0qdnyt?file=/src/App.js


  2. Here, you got the setError as props from the parent component hence it isn’t updating the error state immediately.

    You shouldn’t pass the setState directly, as the setState function will not change the state immediately according to the Documentation.

    You can check out the following:

    Can we pass setState as props from one component to other and change parent state from child component in React?

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search