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

如何在Yup/Formik中实现嵌套条件验证?

Yup/Formik嵌套对象的条件必填验证方案

先看你原本的同级字段条件验证写法,这是没问题的:

addShippingAddress: Yup.boolean(),
name: Yup.string().when('addShippingAddress', {
  is: true,
  then: (schema) => schema.required('Field is required'),
}),

但当需要验证的字段在嵌套对象里,而触发条件的字段在父级对象时,直接写字段名会找不到,导致验证失效,就像你遇到的这个情况:

shipping: Yup.object().shape({
  addShippingAddress: Yup.boolean(),
  address: Yup.object().shape({
    name: Yup.string().when('addShippingAddress', {
      // 始终提示addShippingAddress未定义,即使addShippingAddress不为true也会强制设为必填
      is: true,
      then: (schema) => schema.required('Field is required'),
      otherwise: (schema) => schema,
    }),
  }),
}),

给你几个可行的解决办法:

方法一:用相对路径引用父级字段

Yup支持通过../来访问父级对象的字段,直接修改when的字段参数即可:

shipping: Yup.object().shape({
  addShippingAddress: Yup.boolean(),
  address: Yup.object().shape({
    name: Yup.string().when('../addShippingAddress', {
      is: true,
      then: (schema) => schema.required('此字段为必填项'),
      otherwise: (schema) => schema,
    }),
  }),
}),

方法二:把验证逻辑提至父级对象控制

如果嵌套对象里有多个字段需要根据父级条件控制,可以在父级对象的address字段上用when来整体修改嵌套的验证规则:

shipping: Yup.object().shape({
  addShippingAddress: Yup.boolean(),
  address: Yup.object().shape({
    name: Yup.string(),
    // 其他嵌套字段...
  }).when('addShippingAddress', {
    is: true,
    then: (schema) => schema.shape({
      name: Yup.string().required('此字段为必填项'),
      // 其他需要必填的字段...
    }),
    otherwise: (schema) => schema,
  }),
}),

方法三:结合Formik手动写验证函数

如果业务逻辑比较复杂,直接用Yup的规则搞不定,可以在Formik里自定义validate函数,手动控制验证逻辑:

const validate = (values) => {
  const errors = {};
  // 当父级开关为true时,检查嵌套字段
  if (values.shipping?.addShippingAddress) {
    if (!values.shipping?.address?.name) {
      // 逐层创建错误对象,对应表单字段路径
      errors.shipping = errors.shipping || {};
      errors.shipping.address = errors.shipping.address || {};
      errors.shipping.address.name = '此字段为必填项';
    }
  }
  return errors;
};

// 在Formik组件中使用这个验证函数
<Formik
  initialValues={{
    shipping: {
      addShippingAddress: false,
      address: { name: '' }
    }
  }}
  // 可以保留基础的validationSchema,再结合自定义validate
  validationSchema={/* 你的基础schema */}
  validate={validate}
  onSubmit={(values) => {
    // 提交逻辑
    console.log(values);
  }}
>
  {/* 表单内容 */}
</Formik>

这几种方法里,方法一最适合简单的单字段嵌套验证,写法最简洁;方法二适合批量控制嵌套对象的多个字段;方法三灵活度最高,能处理各种复杂场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 04:32:54