You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mui DateTimePicker与react-hook-form错误行为不一致求助

问题

在使用react-hook-form控制的表单中集成Mui DateTimePicker组件,通过disablePast属性验证所选日期为未来日期时,出现错误状态未同步的问题:

  • 选择明日日期→无错误(正常);改选昨日→出现disablePast错误(正常);再改选前日→无错误(异常)
  • 选择两天前的日期→有错误(正常);改为昨日→无错误(异常);改为今日→有错误(异常,今日时间在当前时间之后)

相关代码如下:

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>
  );
}

解决方案

问题核心在于仅依赖Mui的onError回调设置react-hook-form错误状态,但onError仅在错误状态发生变化时触发(如合法→非法、非法→合法的瞬间),连续选择同类型非法日期时不会重复触发,导致状态不同步。

正确做法是将日期验证逻辑统一交给react-hook-form,保留disablePast作为UI层面限制,具体修改如下:

修改后完整代码

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 from "dayjs";
import "dayjs/locale/en-gb";

const MyDateTimePicker = ({ name, control, error }) => {
  const { field } = useController({
    name,
    control,
    rules: {
      validate: (value) => {
        if (!value) return true; // 允许空值,若需必填可添加required规则
        const isFuture = value.isAfter(dayjs());
        return isFuture ? true : "请选择未来的日期时间";
      }
    }
  });

  return (
    <DateTimePicker
      {...field}
      label="future date"
      disablePast
      slotProps={{
        textField: {
          error: !!error,
          helperText: error?.message
        }
      }}
    />
  );
};

export default function App() {
  const {
    control,
    handleSubmit,
    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}
          />
        </form>
      </div>
    </LocalizationProvider>
  );
}

关键说明

  • 利用useController的rules.validate定义验证逻辑,每次字段值变化都会执行验证,确保错误状态实时同步
  • 保留disablePast作为UI层面的禁用限制,避免用户选择过去日期,最终验证逻辑由react-hook-form控制,保证状态一致性
  • 若需设置必填,可在rules中添加required: "此字段不能为空"规则

内容的提问来源于stack exchange,提问作者kougami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 23:55:38