React结合Formik、Yup使用日历选择器时如何注册字段touched状态
问题排查与修复
核心异常原因
- 状态绑定错位:
periodStart字段的error判断错误引用了touched.periodEnd的状态,状态关联和实际字段不匹配。 - 缺少touched状态触发逻辑:MUI 日历选择器完成日期点选时,只会触发值更新的
onChange事件,不会自动触发Formik绑定的blur逻辑,导致对应字段的touched状态始终为false,错误样式无法激活。 - 提示逻辑不合理:
helperText没有结合touched状态判断展示,会在用户未交互时就提前显示错误提示。
可直接复用的修复代码
import React, { FC, useRef } from "react"; import { Formik, Form, Field } from "formik"; import { KeyboardDatePicker } from "formik-material-ui-pickers"; import * as Yup from "yup"; import moment from "moment"; import { ReportConfig } from "../ReportConfig"; export type DProps = { type: Type | null, currentConfig: ReportConfig | null, }; export const Dialog: FC<DProps> = ({ currentConfig }) => { const form: any = useRef(null); const initialValues = { periodStart: moment(currentConfig?.periodStart), periodEnd: moment(currentConfig?.periodEnd), }; return ( <Formik innerRef={form} initialValues={initialValues} validationSchema={Yup.object().shape({ periodStart: Yup.date() .typeError("Enter a valid date.") .max(Yup.ref("periodEnd"), "Must be before End.") .required("Required"), periodEnd: Yup.date() .typeError("Enter a valid date.") .min(Yup.ref("periodStart"), "Must be after Start.") .required("Required"), })} > {({ values, errors, touched, setFieldTouched }) => ( <Form> <Field variant="inline" autoOk name="periodStart" label="Start Date" inputVariant="outlined" component={KeyboardDatePicker} format="MM/DD/YYYY" // 日期选中后手动标记字段为已交互状态 onChange={() => setFieldTouched("periodStart", true)} error={touched.periodStart && Boolean(errors.periodStart)} helperText={touched.periodStart ? errors.periodStart : ""} /> <Field variant="inline" autoOk name="periodEnd" label="End Date" inputVariant="outlined" component={KeyboardDatePicker} format="MM/DD/YYYY" // 日期选中后手动标记字段为已交互状态 onChange={() => setFieldTouched("periodEnd", true)} error={touched.periodEnd && Boolean(errors.periodEnd)} helperText={touched.periodEnd ? errors.periodEnd : ""} /> </Form> )} </Formik> ); };
优化说明
- 移除了手动传入的
onBlur={handleBlur}逻辑,formik-material-ui-pickers组件已内置Formik的blur事件绑定,手动传入会造成事件触发时序异常。 - 通过
setFieldTouched在日期选中回调里同步更新交互状态,不管用户是手动输入日期还是通过日历点选日期,只要字段值触发校验规则,对应的错误样式就会正常激活。 - 结合
touched状态控制错误提示展示时机,避免初始页面加载时就铺满错误提示,影响使用体验。
内容的提问来源于stack exchange,提问作者pasi
相关产品推荐
相关产品推荐

