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:
- Select tomorrow’s date – no error (as it should be)
- Change the selected date to yesterday – disablePast error (as it should be)
- 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:
- Enter in a date for two days ago – error (as it should be)
- Increase the date by one, so the value is yesterday – no error, but there should be
- 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
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
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?