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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:45:34