MUI 5 DatePicker结合react-final-form键盘输入异常问题
MUI 5 DatePicker与react-final-form集成年份输入异常问题解决
问题背景
此前使用旧版Material-UI的KeyboardDatePicker结合react-final-form无异常,改用新版@mui/x-date-pickers的DatePicker后,出现年份显示和输入异常问题。
相关代码实现
DatePicker封装组件
function DateInput(props: any) { return ( <LocalizationProvider dateAdapter={AdapterDateFns}> <DatePicker {...props} renderInput={(params: any) => { return <TextField {...params} />; }} /> </LocalizationProvider> ); }
react-final-form的Field封装
function DateFormField({ name, label, inputFormat }: { name: string; label: string; inputFormat: string; }) { return ( <Field name={name} parse={(value) => formatDateTime(value)} type="date"> {({ input, meta: { touched, invalid, error } }) => ( <DateInput {...input} label={label} inputFormat={inputFormat} /> )} </Field> ); }
表单集成
<Form initialValues={formInitialValues} onSubmit={handleSubmitClick}> {({ handleSubmit }) => ( <form onSubmit={handleSubmit}> <DateFormField name="asOfDate" label="As Of Date" inputFormat="MM/dd/yyyy" /> <Button type="submit" variant="contained" color="primary"> Submit </Button> </form> )} </Form>
问题表现
- 初始值设为
new Date("0002-07-28")时,控件显示07/27/2002,而非预期的07/28/0002 - 修改年份时,输入框会自动将两位数年份补全为21世纪年份,例如删除原有年份后输入第一个
2,控件直接显示2002
解决方案
1. 修复初始值时区偏移问题
JavaScript的new Date()会基于本地时区解析ISO格式日期,导致早期日期出现偏移。改用date-fns的parseISO构造UTC日期避免该问题:
import { parseISO } from 'date-fns'; const formInitialValues = { asOfDate: parseISO('0002-07-28T00:00:00Z') // 使用UTC时间初始化 };
2. 自定义DatePicker的年份解析逻辑
通过parse prop覆盖默认解析行为,确保支持4位完整年份输入,禁用自动补全21世纪的逻辑:
import { parse } from 'date-fns'; function DateInput(props: any) { // 自定义解析函数,严格按输入格式解析年份 const customParse = (value: string, formatStr: string) => { return parse(value, formatStr, new Date(), { useAdditionalDayOfYearTokens: true, }); }; return ( <LocalizationProvider dateAdapter={AdapterDateFns}> <DatePicker {...props} parse={customParse} format={props.inputFormat} renderInput={(params: any) => { return <TextField {...params} />; }} /> </LocalizationProvider> ); }
3. 对齐react-final-form的parse逻辑
确保Field的parse函数和DatePicker的解析规则一致,避免数据不一致:
import { parse } from 'date-fns'; function DateFormField({ name, label, inputFormat }: { name: string; label: string; inputFormat: string; }) { // 使用和DatePicker一致的解析函数 const parseDate = (value: string) => { return parse(value, inputFormat, new Date()); }; return ( <Field name={name} parse={parseDate} type="date"> {({ input, meta: { touched, invalid, error } }) => ( <DateInput {...input} label={label} inputFormat={inputFormat} /> )} </Field> ); }
4. 禁用自动补全与掩码输入(可选)
如果需要完全自由的年份输入,可以禁用DatePicker的掩码输入功能,避免自动补全年份:
// 在DatePicker中添加disableMaskedInput <DatePicker {...props} parse={customParse} format={props.inputFormat} disableMaskedInput renderInput={(params: any) => { return <TextField {...params} />; }} />
说明
问题根源在于date-fns的默认年份解析行为(自动将两位数年份映射到2000-2099),以及MUI DatePicker的自动补全逻辑。通过自定义解析函数、对齐表单解析规则、处理时区偏移,可以解决年份显示和输入异常的问题。
内容的提问来源于stack exchange,提问作者C. Helling
相关产品推荐
相关产品推荐

