Formik表单复杂Yup验证开发问题及实现方案咨询
Yup表单验证Schema解决方案
问题1:修复总和校验的"payments.reduce is not a function"错误
你之前的.test方法参数使用错误,Yup对象级别的test回调第一个参数是整个表单的values对象,而非单独的payments和invoiceLines字段。另外需要处理字段为空/非数组的情况,同时给reduce添加初始值避免空数组报错。
修正后的代码如下:
const applyPaymentFormValidation = yup.object().shape({ // 原有字段定义... invoiceLines: yup.array().of(/* 原有验证逻辑 */), }).test( "total_match", "客户支付总额必须等于已应用支付总额", function(values) { // 处理payments为空/非数组的情况,默认转为空数组 const payments = Array.isArray(values.payments) ? values.payments : []; // 处理invoiceLines为空/非数组的情况 const invoiceLines = Array.isArray(values.invoiceLines) ? values.invoiceLines : []; // 计算payments.applied总和,加初始值0避免空数组报错 const paymentsTotal = payments.reduce( (total, item) => total + defaultNullUndefined(item.applied, 0), 0 ); // 计算invoiceLines.clientAmountPaid总和 const invoiceLinesTotal = invoiceLines.reduce( (total, item) => total + defaultNullUndefined(item.clientAmountPaid, 0), 0 ); return paymentsTotal === invoiceLinesTotal; } );
错误原因说明
- 原代码中
test回调的参数错误,直接解构payments和invoiceLines会导致拿到的是整个values对象而非对应字段; - 未处理
payments或invoiceLines为null/undefined/非数组的情况,调用reduce会抛出类型错误; reduce未设置初始值,当数组为空时会返回undefined,后续计算会出现NaN。
问题2:实现payments与newPayments的互斥验证
可以通过Yup的when条件验证实现:当payments为空(无数据)时,newPayments必须存在且符合验证规则;反之当newPayments存在时,payments必须为空。
实现代码
const applyPaymentFormValidation = yup.object().shape({ payments: yup.array().of( yup.object().shape({ applied: yup.number(), }) ).when("newPayments", { is: (newPayments) => Array.isArray(newPayments) && newPayments.length > 0, then: yup.array().max(0, "已有新支付记录时,不能同时保留旧支付记录"), otherwise: yup.array(), }), newPayments: yup.array().of( yup.object().shape({ total: yup.number(), paymentType: yup.number().required("请选择支付方式"), date: yup.date() .required("必须提供支付日期") .max(tomorrow, "交易日期不能晚于明天"), paymentNumber: yup.string().nullable(), }) ).when("payments", { is: (payments) => Array.isArray(payments) && payments.length > 0, then: yup.array().max(0, "已有旧支付记录时,不能同时添加新支付记录"), otherwise: yup.array().min(1, "无旧支付记录时,必须添加新支付记录").required(), }), // 原有invoiceLines字段定义... }).test(/* 问题1的总和校验逻辑 */);
逻辑说明
- 给
payments添加when规则:当newPayments有数据时,限制payments必须为空数组; - 给
newPayments添加when规则:当payments有数据时,限制newPayments必须为空数组;当payments为空时,newPayments必须至少有一条记录并满足内部字段验证。
内容的提问来源于stack exchange,提问作者WhaleWatcher2023
相关产品推荐
相关产品推荐

