Yup多层嵌套对象校验:map为true时mapping.name必填实现方法
问题原因
你的校验规则不生效,核心是yup.when()的路径是相对于当前schema所在字段层级做相对解析的。你在created字段的object schema上调用when('mapping.map'),同时在then回调里只声明了mapping下的name规则,一方面路径匹配逻辑容易出偏差,另一方面这种写法会覆盖created对象下其他字段的原有校验规则,最终导致条件判断无法正常触发。
正确写法
最稳妥、路径不容易出错的方式,是把条件校验下沉到离目标字段最近的层级,直接在mapping.name字段上声明同层级的map字段依赖,同时先把所有字段的基础校验规则声明完整,避免规则被覆盖:
const validationSchema = yup.object({ created: yup.object({ position: yup.number().required(), name: yup.string().required(), type: yup.string().required(), desc: yup.string(), mapping: yup.object({ defaultValue: yup.string(), map: yup.boolean(), // 当前层级就是mapping对象,直接用相对路径'map'即可定位到依赖字段 name: yup.string().when('map', { is: true, then: (schema) => schema.required('name is required'), otherwise: (schema) => schema.notRequired() }) }) }) })
写法说明
- 不要在父级字段上通过
when嵌套声明子字段规则,这种写法很容易因为路径解析、schema覆盖问题导致校验失效 - 如果确实需要在父级声明条件规则,要使用
.shape()方法追加规则,而不是直接返回新的object schema覆盖原有结构,同时要保证路径和当前层级匹配:
// 不推荐的父级声明写法,仅做参考 const validationSchema = yup.object({ created: yup.object({ position: yup.number().required(), name: yup.string().required(), type: yup.string().required(), desc: yup.string(), mapping: yup.object({ defaultValue: yup.string(), map: yup.boolean(), name: yup.string() }) }).when('mapping.map', { is: true, then: (schema) => schema.shape({ mapping: yup.object({ name: yup.string().required('name is required') }) }) }) })
测试验证:当
created.mapping.map值为false时,mapping.name允许为空;当值为true时,mapping.name为空会触发必填提示,符合需求预期。
内容的提问来源于stack exchange,提问作者Rob Terrell
相关产品推荐
相关产品推荐

