如何使用Yup验证数组对象中的重复值?——校验existingMortgage与newMortgage中contractNum的重复项
如何用Yup验证数组内及跨数组的contractNum重复值?
嘿,这个问题我刚好处理过,用Yup的自定义test方法就能完美解决!咱们分三个场景来实现验证:existingMortgage内部重复、newMortgage内部重复,还有两个数组之间的跨数组重复。结合你的Formik数据结构,我给你写个完整的验证方案:
完整的Yup验证Schema
import * as Yup from 'yup'; const mortgageValidationSchema = Yup.object().shape({ existingMortgage: Yup.array().of( Yup.object().shape({ contractNum: Yup.string() .required('合同编号不能为空') // 验证existingMortgage数组内部的重复值 .test( 'internal-existing-duplicate', '该合同编号在已有贷款中重复', function (value) { // 获取当前所在的existingMortgage数组 const currentList = this.parent; // 统计当前contractNum出现的次数 const duplicateCount = currentList.filter(item => item.contractNum === value).length; // 只允许出现1次(即不重复) return duplicateCount <= 1; } ) // 验证与newMortgage数组的跨数组重复 .test( 'cross-new-duplicate', '该合同编号已在新增贷款中存在', function (value) { // 获取整个表单的根数据,拿到newMortgage数组 const newMortgageList = this.root.newMortgage || []; // 检查当前编号是否在新增贷款中存在 return !newMortgageList.some(item => item.contractNum === value); } ), mortgageAmount: Yup.number().required('贷款金额不能为空') }) ), newMortgage: Yup.array().of( Yup.object().shape({ contractNum: Yup.string() .required('合同编号不能为空') // 验证newMortgage数组内部的重复值 .test( 'internal-new-duplicate', '该合同编号在新增贷款中重复', function (value) { const currentList = this.parent; const duplicateCount = currentList.filter(item => item.contractNum === value).length; return duplicateCount <= 1; } ) // 验证与existingMortgage数组的跨数组重复 .test( 'cross-existing-duplicate', '该合同编号已在已有贷款中存在', function (value) { const existingMortgageList = this.root.existingMortgage || []; return !existingMortgageList.some(item => item.contractNum === value); } ), mortgageAmount: Yup.number().required('贷款金额不能为空') }) ) });
关键验证逻辑拆解
1. 数组内部重复验证
针对单个数组(比如existingMortgage)内部的重复,我们用Yup的.test()方法自定义规则:
- 通过
this.parent获取当前字段所在的数组(也就是整个existingMortgage数组) - 过滤数组中所有
contractNum等于当前输入值的项,统计数量;如果数量大于1,说明存在重复,验证失败
2. 跨数组重复验证
要检查两个数组之间的重复,需要拿到另一个数组的数据:
- 通过
this.root获取整个Formik表单的根对象,这样就能访问到newMortgage或existingMortgage数组 - 用
some()方法检查当前输入的contractNum是否已经存在于另一个数组中,如果存在则验证失败
优化小技巧
如果你的数组数据量比较大,用filter统计次数的效率可以优化,改用Set来做去重检查:
// 优化后的内部重复验证 .test( 'internal-existing-duplicate', '该合同编号在已有贷款中重复', function (value) { const currentList = this.parent; const contractNumbers = currentList.map(item => item.contractNum); // 用Set去重,对比去重前后的长度 return new Set(contractNumbers).size === contractNumbers.length; } )
不过这种方式是对整个数组做验证,如果需要让具体重复的输入框触发错误提示,还是用之前的filter统计方式更精准。
内容的提问来源于stack exchange,提问作者Marshall Smith
相关产品推荐
相关产品推荐

