React TSX + react-hook-form + Yup 条件展示表单字段校验实现问题
Yup 多级条件展示字段校验修复方案
原代码存在的问题
- 语法错误:
case 'webmoney缺失闭合单引号,直接导致代码运行报错 - 逻辑不符合需求:bank_transfer 分支下直接将 payment_system_A、payment_system_B 对应的所有字段设为必填,没有根据两个复选框的选中状态做条件判断
- 依赖监听缺失:没有将 payment_system_A、payment_system_B 加入校验依赖,字段选中状态变化时不会触发校验规则更新
修正后的代码实现
const validationSchema = yup.object().shape({ id: yup.number().required(), title: yup.string().required('Required field'), is_default: yup.number().oneOf([0, 1]), is_confirmed: yup.number().oneOf([1], t('Confirm that the payment details on this form are correct')), // 支付系统复选框和id同级,如果是放在method_fields下可移到内层定义 payment_system_A: yup.boolean(), payment_system_B: yup.boolean(), method_fields: yup.object().when('id', (id) => { const paymentType = paymentMethod[id]; switch (paymentType) { case 'webmoney': return yup.object().shape({ webmoney_account_number: yup.string().required('Required field'), webmoney_purpose_of_payment: yup.string().required('Required field'), // 第三个webmoney字段按实际需求补充校验规则 }); case 'bank_transfer': return yup.object().shape({ // 可在这里定义bank_transfer场景下的公共必填字段 }).when(['payment_system_A', 'payment_system_B'], ([isASelected, isBSelected]) => { const fields = {}; // 选中payment_system_A时加载对应字段校验 if (isASelected) { Object.assign(fields, { payments_name: yup.string().required('Required field'), payments_nickname: yup.string().required('Required field'), payments_address: yup.string().required('Required field'), payments_bank_account_number: yup.string().required('Required field'), payments_bank_routing_number: yup.number().required('Required field'), payments_bank_name: yup.string().required('Required field') }); } // 选中payment_system_B时加载对应字段校验 if (isBSelected) { Object.assign(fields, { international_transfers_name: yup.string().required('Required field'), international_transfers_address: yup.string().required('Required field'), international_transfers_account: yup.string().required('Required field'), international_transfers_bank: yup.string().required('Required field'), international_transfers_bank_address: yup.string().required('Required field'), international_transfers_swifts: yup.string().required('Required field'), international_transfers_etc: yup.string().required('Required field') }); } return yup.object().shape(fields); }); default: return yup.object().shape({}); } }) });
注意事项
- 若使用 Yup v1 版本,when 回调的第二个参数需要接收 context 对象,从 context 中取 schema 构造返回值,可对应版本官方规则调整写法
- 如果 payment_system_A、payment_system_B 字段存放在 method_fields 内层对象中,需要将嵌套 when 的依赖参数改为对应内层字段名,不需要跨层级引用
内容的提问来源于stack exchange,提问作者MAKEDA
相关产品推荐
相关产品推荐

