useFormik与Yup校验:错误信息仅触发一次的问题求助
解决Formik+Yup校验错误显示时机及重复显示问题
一、错误仅在切换Tab/提交时显示的修复
Formik默认仅在字段被touched(失焦)或表单提交时触发错误显示。你的自定义onChange事件只更新了字段值,未标记字段为已触碰状态,导致错误无法实时展示。
修改CustomInput的onChange逻辑,手动触发字段的touched状态更新:
onChange={(e) => { handleChange({ target: { name: "message", value: e } }); // 标记字段为已触碰,触发实时校验 formik.setFieldTouched("message", true); setCustomValidation({ ...customValidation, message: e.indexOf("RELATED.LINK") === -1 && formik.values.category !== `${CATEGORY_CANDIDATE_EMAIL}`, }); }}
修改后输入过程中会实时触发Yup校验,错误信息将即时显示,无需等待切换Tab或提交操作。
二、错误信息重复显示的修复
重复显示的核心原因是CustomInput组件本身已通过errorMessage={formik.errors.message}展示错误,同时又额外添加了<ErrorMessage>组件,两者渲染了同一条错误文本。
解决方法二选一:
方案1:保留CustomInput的错误展示,移除额外
直接删除新增的<ErrorMessage>组件,仅通过CustomInput的errorMessage属性展示错误,同时完善错误信息的判断逻辑:
<CustomInput id="message" name="message" value={formik.values.message} bodyText={messageTextLocalized} readonly={false} previewModeError={false} placeHolderText={msgEnterEmailTemplatemessageTextLocalized} onChange={(e) => { handleChange({ target: { name: "message", value: e } }); formik.setFieldTouched("message", true); setCustomValidation({ ...customValidation, message: e.indexOf("RELATED.LINK") === -1 && formik.values.category !== `${CATEGORY_CANDIDATE_EMAIL}`, }); }} hasError={ customValidation.message || (formik.errors.message && formik.touched.message) } errorMessage={formik.errors.message || (customValidation.message ? "the RELATED.LINK text is required" : "")} />
方案2:用统一显示,移除CustomInput的errorMessage
修改CustomInput不再处理错误文本,改用Formik的<ErrorMessage>组件统一展示,自定义校验错误单独处理:
<CustomInput id="message" name="message" value={formik.values.message} bodyText={messageTextLocalized} readonly={false} previewModeError={false} placeHolderText={msgEnterEmailTemplatemessageTextLocalized} onChange={(e) => { handleChange({ target: { name: "message", value: e } }); formik.setFieldTouched("message", true); setCustomValidation({ ...customValidation, message: e.indexOf("RELATED.LINK") === -1 && formik.values.category !== `${CATEGORY_CANDIDATE_EMAIL}`, }); }} hasError={ customValidation.message || (formik.errors.message && formik.touched.message) } /> {/* Formik内置组件展示Yup校验错误 */} <ErrorMessage name="message" component="div" className="error-text" /> {/* 自定义校验错误单独展示 */} {customValidation.message && ( <div className="error-text">the RELATED.LINK text is required</div> )}
三、额外优化:移除冗余的自定义校验
你自定义的RELATED.LINK校验逻辑已经在Yup的when规则中实现,完全可以去掉customValidation状态,简化代码:
// 保留原有Yup校验规则即可 const validationSchema = yup.object().shape({ message: yup .string() .when(["category"], { is: (category) => category !== CATEGORY_CANDIDATE_EMAIL.toString(), then: yup.string().matches(/RELATED.LINK/, "the RELATED.LINK text is required" ), }) .required("error message required message") .nullable() .trim(), category: yup .string() .required("error message required category") .nullable() .trim(), });
对应的CustomInput onChange逻辑简化为:
onChange={(e) => { handleChange({ target: { name: "message", value: e } }); formik.setFieldTouched("message", true); }} hasError={formik.errors.message && formik.touched.message} errorMessage={formik.errors.message || ""}
内容的提问来源于stack exchange,提问作者Hyma S
相关产品推荐
相关产品推荐

