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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 12:18:21