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

Formik调用setErrors方法时其他字段校验错误被重置问题

问题原因

Formik 提供的 setErrors 方法默认是全量替换整个 errors 错误对象,而非增量合并更新。调用时只传入包含 postalCode 字段错误的对象,会直接覆盖掉之前 Yup 校验生成的 name、surname 字段错误,最终就会出现其他字段校验错误丢失的情况。

解决方法

以下三种方案都能解决问题,按实际场景选择即可:

方案1:使用单字段错误设置API(最简便)

Formik 内置了专门用于设置单个字段错误的方法 setFieldError,方法内部会自动保留其他字段的已有错误,不会触发全量覆盖,直接调用即可:

// 第一个参数传字段名,第二个参数传错误提示内容
formik.setFieldError('postalCode', 'error in postal code');

方案2:手动合并现有错误后再调用setErrors

如果需要批量更新多个字段错误,不想逐个调用 setFieldError,可以先取到当前已存在的所有校验错误,和新的错误对象做浅合并后再传入 setErrors:

formik.setErrors({
  // 先展开保留原有所有错误
  ...formik.errors,
  // 再追加/覆盖要设置的字段错误
  postalCode: 'error in postal code'
});

方案3:将异步接口校验纳入Formik统一校验流程(推荐长期维护用)

最规范的做法是不在表单事件外层手动设置错误,把邮编的接口异步校验逻辑写到 Formik 配置的 validate 字段里,和 Yup 的校验规则一起由 Formik 统一调度,所有校验结果会自动合并,完全不需要手动处理错误覆盖问题:

const formik = useFormik({
  enableReinitialize: true,
  initialValues: {
    name: insurer && get(insurer, "name", null),
    surname: insurer && get(insurer, "surname", null),
    postalCode: insurer && get(insurer, "postalCode", null),
  },
  // 自定义异步校验逻辑
  validate: async (values) => {
    const errors = {};
    // 替换成实际项目中的邮编校验接口调用逻辑
    const isPostalCodeValid = await checkPostalCodeApi(values.postalCode);
    if (!isPostalCodeValid) {
      errors.postalCode = 'error in postal code';
    }
    return errors;
  },
  onSubmit: (values) => {
    // 表单提交逻辑
  },
  validationSchema: Yup.object().shape({
    name: Yup.string()
      .typeError("Preenche este campo")
      .required("Preenche este campo"),
    surname: Yup.string()
      .typeError("Preenche este campo")
      .required("Preenche este campo"),
  }),
});

这种方式的好处是校验触发时机完全和 Formik 内置逻辑对齐,失焦、输入、提交时都会按配置规则自动跑校验,不需要额外写事件监听触发接口调用,后续新增其他自定义校验规则也更好维护。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 17:01:18