如何在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
相关产品推荐
相关产品推荐

