mui-x DateTimePicker v6:如何适配第三方表单库的onChange与onBlur?
MUI-X DateTimePicker v6 与 Formik 等第三方表单库兼容方案
问题描述
MUI-X DateTimePicker v5版本中,onBlur和onChange会返回原生事件对象,可直接配合第三方表单库使用(例如写法:onChange={e => onChange(e.target.value)})。但升级至v6版本后,这两个回调返回的是date或string类型的值,而非事件对象,导致无法直接沿用旧的表单库适配逻辑。
预期效果
希望DateTimePicker能与Formik及其他第三方表单库兼容,调用方式如下:
<DateTimePicker value={value} onChange={newValue => onChange(new ChangeEvent(...))} onBlur={() => onBlur(new FocusEvent('blur'))} />
解决方案
1. 直接传递值(推荐方案)
Formik等表单库并不强制要求传入原生事件对象,核心需求是获取更新后的值并同步到表单状态。直接使用Formik的setFieldValue或适配useField钩子即可,写法简洁且符合官方推荐:
方式一:使用setFieldValue
import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker'; import { useFormik } from 'formik'; const MyForm = () => { const formik = useFormik({ initialValues: { date: new Date() }, onSubmit: (values) => console.log('提交的值:', values), }); return ( <form onSubmit={formik.handleSubmit}> <DateTimePicker value={formik.values.date} onChange={(newValue) => formik.setFieldValue('date', newValue)} onBlur={() => formik.handleBlur({ target: { name: 'date' } })} /> <button type="submit">提交表单</button> </form> ); };
方式二:封装为Formik字段组件
利用Formik的useField钩子封装可复用的DateTimePicker组件,后续直接调用即可:
import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker'; import { useField, useFormikContext } from 'formik'; const FormikDateTimePicker = ({ name, ...restProps }) => { const [field] = useField(name); const { setFieldValue } = useFormikContext(); return ( <DateTimePicker {...restProps} value={field.value} onChange={(newValue) => setFieldValue(name, newValue)} onBlur={() => field.onBlur({ target: { name } })} /> ); }; // 使用示例 const MyForm = () => { const formik = useFormik({ initialValues: { appointmentTime: new Date() }, onSubmit: (values) => console.log(values), }); return ( <form onSubmit={formik.handleSubmit}> <FormikDateTimePicker name="appointmentTime" label="预约时间" /> <button type="submit">提交</button> </form> ); };
2. 模拟事件对象(适配旧代码)
如果因为历史代码依赖事件对象,必须保持原有回调形式,可以手动构造符合React事件接口的对象:
// 构造适配Formik的ChangeEvent const createChangeEvent = (name: string, value: Date | null) => ({ target: { name, value }, preventDefault: () => {}, stopPropagation: () => {}, }) as React.ChangeEvent<HTMLInputElement>; // 构造适配Formik的FocusEvent const createBlurEvent = (name: string) => ({ target: { name }, preventDefault: () => {}, stopPropagation: () => {}, }) as React.FocusEvent<HTMLInputElement>; // 使用示例 <DateTimePicker value={formik.values.date} onChange={(newValue) => formik.handleChange(createChangeEvent('date', newValue))} onBlur={() => formik.handleBlur(createBlurEvent('date'))} />
内容的提问来源于stack exchange,提问作者RikuS3n
相关产品推荐
相关产品推荐

