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

React Formik表单条件必填验证:解决Yup循环依赖问题

解决Yup表单验证循环依赖:字段可选转必填的正确实现

问题场景

表单所有字段默认可选,但只要有任意一个字段输入内容,所有字段必须变为必填。使用Yup的when方法尝试实现时,触发了Cyclic dependency, node was:"password"循环依赖错误。

实现方案

核心是通过自定义测试规则替代when的字段间交叉引用,避免循环依赖。具体代码如下:

import * as Yup from "yup";

const validationSchema = Yup.object().shape({
  username: Yup.string()
    .test(
      "required-if-any-filled",
      "用户名不能为空",
      function (value) {
        const { username, password, email } = this.parent;
        // 检查是否有任意字段已填写
        const hasFilledField = [username, password, email].some(
          item => item?.trim()
        );
        // 无字段填写时放行,否则当前字段必须有值
        return !hasFilledField || !!value?.trim();
      }
    ),
  password: Yup.string()
    .test(
      "required-if-any-filled",
      "密码不能为空",
      function (value) {
        const { username, password, email } = this.parent;
        const hasFilledField = [username, password, email].some(
          item => item?.trim()
        );
        return !hasFilledField || !!value?.trim();
      }
    ),
  email: Yup.string()
    .email("邮箱格式不正确")
    .test(
      "required-if-any-filled",
      "邮箱不能为空",
      function (value) {
        const { username, password, email } = this.parent;
        const hasFilledField = [username, password, email].some(
          item => item?.trim()
        );
        return !hasFilledField || !!value?.trim();
      }
    )
});

方案说明

  • 利用this.parent获取整个表单的字段值,避免字段间直接引用,从根源上解决循环依赖问题。
  • 每个字段的验证逻辑一致:当没有任何字段填写时,保持可选;只要有一个字段有内容,所有未填写的字段都会触发必填校验。
  • 可根据实际表单字段,调整hasFilledField判断中的字段数组。

原方案报错原因

使用when时如果出现字段A依赖字段B、字段B又依赖字段A的交叉引用,就会形成循环依赖。例如尝试when('username', () => Yup.string().required())同时给password设置类似规则,Yup无法解析这种相互依赖的验证逻辑,因此抛出循环依赖错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:42:49