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

MUI X DatePicker搭配react-hook-form提交表单时值异常问题

问题根因

两种写法的核心问题都是没有正确打通MUI DatePicker的受控值和react-hook-form的表单状态,各自的错误点如下:

  • 方式1(Controller写法):完全没有使用render参数里传入的field对象提供的value和onChange方法,自己额外维护了一份本地state存日期值。调用setOriginalReleaseDate只会修改组件本地状态,从来没有把值同步给react-hook-form内部维护的表单store,所以提交时拿到的永远是Controller初始设置的null。
  • 方式2(直接register写法):register方法只能监听原生input元素的输入、变更事件,而通过DatePicker弹出面板选日期时,值是存在MUI组件内部状态里的,不会触发原生input的change事件,自然没法把选中的日期同步给表单。只有手动在输入框里敲日期时才会触发原生输入事件,所以才会出现手动输入能拿值、面板选值拿空串的问题。
正确实现方案

MUI X DatePicker是标准的第三方受控组件,不能直接用register绑定,必须通过Controller(或useController钩子)对接react-hook-form,不需要额外写useState维护日期值,值的同步全交给Controller处理即可。

  1. 首先建议把LocalizationProvider上移到应用根组件或者表单外层,不需要每个日期字段都重复嵌套包裹:
//  App.jsx 或者表单外层组件
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';

function App() {
  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      {/* 其他业务组件、表单放在这里 */}
    </LocalizationProvider>
  )
}
  1. 表单内的日期字段绑定写法:
import { useForm, Controller } from 'react-hook-form';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import TextField from '@mui/material/TextField';

export default function RecordForm() {
  const { control, handleSubmit } = useForm({
    // 所有表单字段默认值统一在useForm里初始化,不需要单独写useState
    defaultValues: {
      original_release_date: null,
      reissue_release_date: null
    }
  });

  const onFormSubmit = (formData) => {
    console.log('提交的表单数据', formData);
    // 这里拿到的日期字段值就是选中的标准Date对象,不会出现null/空串问题
  };

  return (
    <form onSubmit={handleSubmit(onFormSubmit)}>
      <Controller
        name="original_release_date"
        control={control}
        // 要加校验规则直接写在rules里即可,比如必填
        rules={{ required: '请选择原始发行日期' }}
        render={({ field, fieldState: { error } }) => (
          <DatePicker
            label="Original Release Date"
            value={field.value}
            onChange={field.onChange}
            renderInput={(params) => (
              <TextField
                {...params}
                {...field}
                error={!!error}
                helperText={error?.message}
              />
            )}
          />
        )}
      />

      <Controller
        name="reissue_release_date"
        control={control}
        rules={{ required: '请选择再版发行日期' }}
        render={({ field, fieldState: { error } }) => (
          <DatePicker
            label="Reissue Release Date"
            value={field.value}
            onChange={field.onChange}
            renderInput={(params) => (
              <TextField
                {...params}
                {...field}
                error={!!error}
                helperText={error?.message}
              />
            )}
          />
        )}
      />

      <button type="submit">提交表单</button>
    </form>
  )
}

这种写法下,不管是手动输入日期还是通过弹出面板选择日期,值都会自动同步到react-hook-form的表单状态,提交时能直接拿到正确的日期值,校验规则也能正常触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 04:36:23