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

使用@mui/x-date-pickers与Formik时错误消息不显示的问题

问题:MUI DatePicker结合Formik时,手动输入过去日期不显示错误提示

在React项目中使用@mui/x-date-pickers的DatePicker组件,结合Formik做表单验证时,手动输入过去的日期,错误消息无法正常显示。相关代码如下:

DatePicker组件代码

<LocalizationProvider
  adapterLocale={locale}
  dateAdapter={AdapterDayjs}
>
  <DatePicker
    label={t('test.form.license-expiry-date')}
    id={t('test.form.license-expiry-date')}
    name="dLExpDate"
    value={dayjs(values.dLExpDate)}
    onChange={date => {
      if (date) {
        const newDate = date.toDate();
        const formattedStartDate = format(newDate, 'dd-MM-yyyy');

        handleChange('dLExpDate')(formattedStartDate);
        // Set the field as touched
        setFieldTouched('dLExpDate', true, false);

        // Simulate onBlur behavior
        if (!errors.dLExpDate) {
          props.setFieldValue(
            'dLExpDate',
            transformDateString(formattedStartDate)
          );
        }
      } else {
        // Handle the case when the date is deleted
        handleChange('dLExpDate')('');
        setFieldTouched('dLExpDate', true, false);
        props.setFieldValue('dLExpDate', null); // Set to null or handle as needed
      }
    }}
    disablePast="true"
    orientation="portrait"
    error={errors.dLExpDate && touched.dLExpDate}
    helperText={touched.dLExpDate && errors.dLExpDate}
  />
</LocalizationProvider>

Formik配置代码

<Formik
  initialValues={{
    dLExpDate: null,
  }}
  validationSchema={validator({
    dLExpDate: {
      validatorKey: 'dLExpDate',
      required: true,
    },
  })}
>
  {/* Other form components */}
</Formik>

Yup验证规则代码

dLExpDate: function (t) {
  return Yup.string()
    .oneOfLengths([10], t('test.error.date'))
    .matches(dateRegExp, t('test.error.date'))
    .test('date', 'Invalid date. Must be today or later', function (value) {
      if (!value) {
        return true; // Skip validation if the value is empty
      }
      const selectedDate = new Date(value);
      const currentDate = new Date();
      debugger;
      return selectedDate >= currentDate;
    });
},

尽管已将字段设为已触碰状态,且配置了error={errors.dLExpDate && touched.dLExpDate}的错误显示条件,但错误消息仍未显示。


原因分析
  1. 字段更新逻辑冲突:onChange中先调用handleChange设置格式化日期,之后又通过props.setFieldValue修改字段值,两次更新可能导致Formik的验证流程未正常触发,errors对象未更新。
  2. disablePast属性类型错误:设置为字符串"true"而非布尔值true,虽然不影响手动输入,但属于配置错误,可能引发其他潜在问题。
  3. 日期解析兼容性问题:用原生new Date(value)解析dd-MM-yyyy格式字符串,部分浏览器会解析错误,导致日期比较结果不正确,验证逻辑误判为合法日期。
  4. 验证触发时机未对齐:虽然调用了setFieldTouched,但字段值更新后未触发Formik的重新验证,errors未同步更新,导致错误提示不渲染。

解决建议

1. 修正disablePast属性类型

将disablePast="true"改为disablePast={true},确保是布尔值配置:

<DatePicker
  // ...其他属性
  disablePast={true}
/>

2. 简化onChange逻辑,确保验证触发

去掉冗余的字段更新操作,直接用Formik的setFieldValue和setFieldTouched,避免多次修改导致的验证异常:

onChange={date => {
  const formattedDate = date ? date.format('DD-MM-YYYY') : null;
  setFieldValue('dLExpDate', formattedDate);
  setFieldTouched('dLExpDate', true);
}}

3. 修复Yup验证中的日期解析问题

改用dayjs解析日期,避免原生Date的兼容性问题,同时统一日期比较逻辑:

dLExpDate: function (t) {
  return Yup.string()
    .oneOfLengths([10], t('test.error.date'))
    .matches(dateRegExp, t('test.error.date'))
    .test('date', 'Invalid date. Must be today or later', function (value) {
      if (!value) return true;
      
      // 使用dayjs指定格式解析,确保正确性
      const selectedDate = dayjs(value, 'DD-MM-YYYY');
      if (!selectedDate.isValid()) return false;
      
      // 取当天起始时间,避免时分秒影响比较结果
      const currentDate = dayjs().startOf('day');
      return selectedDate.isAfter(currentDate) || selectedDate.isSame(currentDate);
    });
},

4. 调试验证状态

在DatePicker组件中添加日志,确认errors.dLExpDate和touched.dLExpDate的实际值,排查是否验证逻辑未生成错误:

console.log('dLExpDate error:', errors.dLExpDate, 'touched:', touched.dLExpDate);

5. 确保Formik验证配置正确

检查Formik的validateOnChange和validateOnBlur是否开启(默认均为true),如果手动修改过配置,需确保开启实时验证:

<Formik
  // ...其他配置
  validateOnChange={true}
  validateOnBlur={true}
>
  {/* ... */}
</Formik>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 08:36:00