Inconsistent error behaviour with Mui DateTimePicker and react-hook-form.

huangapple go评论71阅读模式
英文:

Inconsistent error behaviour with Mui DateTimePicker and react-hook-form

问题

以下是您要翻译的内容:

"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?"

英文:

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 &quot;@mui/x-date-pickers/AdapterDayjs&quot;;
import { LocalizationProvider } from &quot;@mui/x-date-pickers/LocalizationProvider&quot;;
import { useForm, useController } from &quot;react-hook-form&quot;;
import { DateTimePicker } from &quot;@mui/x-date-pickers/DateTimePicker&quot;; // v6.0.4
import &quot;dayjs/locale/en-gb&quot;;

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

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

  const onSubmit = (data) =&gt; console.log(data);

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

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?

答案1

得分: 1

已解决,完全取消setError,并将自己的验证作为react-hook-form的规则的一部分编写。

工作示例:https://codesandbox.io/s/eloquent-kowalevski-0qdnyt?file=/src/App.js

英文:

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

得分: -1

在这里,您从父组件获取了props中的setError,因此它不会立即更新错误状态

不应直接传递setState,因为根据文档,setState函数不会立即更改状态。

您可以查看以下内容:

在React中可以从一个组件将setState作为props传递给另一个组件并从子组件更改父组件状态吗?

英文:

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?

huangapple
  • 本文由 发表于 2023年4月4日 05:33:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75923936.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定