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处理即可。
- 首先建议把
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> ) }
- 表单内的日期字段绑定写法:
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
相关产品推荐
相关产品推荐

