React-Datepicker搭配Formik+Yup首次失焦仅required校验生效问题
问题根因
该现象本质是两个逻辑不匹配:
- React-Datepicker的默认事件触发逻辑不会在首次选值时同步触发Formik的字段触摸标记更新
- Formik默认仅展示**已标记为touched(已触摸)**字段的校验错误,首次操作时只有必填校验因为值为空触发,非必填的规则虽然校验了但因为字段没标记为touched,错误不会展示,不是校验没生效。
解决方案
第一步:补充导入触摸状态更新方法
从useFormikContext中新增解构setFieldTouched方法:
const { setFieldValue, validateField, handleBlur, setFieldTouched } = useFormikContext();
第二步:修改值变更逻辑,同步标记触摸状态
修改onChange回调,值更新后立即标记字段为已触摸,再主动触发校验:
onChange={val => { setFieldValue(field.name, val); // 第三个参数为false表示标记触摸时不自动触发校验,后续主动调用更可控 setFieldTouched(field.name, true, false); validateField(field.name); }}
第三步:修复失焦和日历关闭事件的逻辑
React-Datepicker的onBlur事件返回的target不一定携带正确的字段名,需要手动指定,同时优化日历关闭的校验逻辑:
onBlur={() => { // 手动构造Formik handleBlur需要的事件对象,指定字段名 handleBlur({ target: { name: field.name } }); }} onCalendarClose={() => { // 关闭日历时如果已经选值,直接标记触摸+触发校验 setFieldTouched(field.name, true, true); }}
可选:修复Yup日期校验的时间偏差问题
当前写的min(new Date())取的是Schema初始化时的时间,如果打开表单后停留到第二天再校验,会出现日期判断错误,改成函数形式动态取当前时间:
startDate: yup.date().nullable().required('Start Date is required') .min(() => new Date(), 'Start Date must be later than today'),
调整后首次选择日期就能触发全量校验,错误信息会正常展示。
内容的提问来源于stack exchange,提问作者gene b.
相关产品推荐
相关产品推荐

