带自定义输入项的复选框组Yup验证失效,求技术指导
问题分析与解决方案
先拆解你当前验证规则的核心问题:
- 字段类型不匹配:你的
otherOption是单个复选框,若用Formik这类表单库,它的值通常是布尔值(选中为true,未选为false),但你定义为yup.array(),导致后续条件判断逻辑完全失效。 - 联合验证缺失:原规则没覆盖「必须至少选一个选项」的全局要求,只单独对
regularOptions和otherOption做分支判断,无法处理既没选常规选项也没选Other的场景。 - 条件判断不严谨:原
when回调里直接取value[0] === 'Other',如果otherOption是数组,应该用value.includes('Other')判断;如果是布尔值,直接判断value即可,依赖第一个元素的写法容错性极差。
修正后的Yup验证Schema
假设你的表单值结构为:
{ regularOptions: string[], // 选中的常规选项数组 otherOption: boolean, // 是否选中Other复选框 otherText: string // Other对应的输入内容 }
对应的验证Schema如下:
import * as yup from 'yup'; const schema = yup.object().shape({ regularOptions: yup.array().of(yup.string()).notRequired(), otherOption: yup.boolean().notRequired(), otherText: yup.string().when('otherOption', { is: true, then: (schema) => schema.required('请输入自定义内容').min(5, '内容至少5个字符').max(20, '内容最多20个字符'), otherwise: (schema) => schema.notRequired() }) }).test( 'at-least-one-selected', '必须选择至少一个选项', function(value) { const { regularOptions, otherOption, otherText } = value; // 两种合法情况:常规选项至少选一个,或选中Other且输入符合长度要求 const hasRegularOption = Array.isArray(regularOptions) && regularOptions.length > 0; const hasValidOtherOption = otherOption && yup.string().min(5).max(20).isValidSync(otherText); return hasRegularOption || hasValidOtherOption; } );
组件额外优化建议
你的组件存在一个潜在问题:otherOption用onClick触发状态更新,建议换成onChange,因为点击复选框的标签也应该触发状态变更,且onChange能更准确地获取选中状态,同时加上受控绑定确保表单值和组件状态同步:
// 替换原otherOption的input <input type="checkbox" name="otherOption" checked={isOtherSelected} onChange={onOtherSelect} />
另外,直接修改DOM值的写法(inputRef.current?.value = '')不够优雅,建议将otherText也纳入表单状态管理,而非直接操作DOM。
内容的提问来源于stack exchange,提问作者noblerare
相关产品推荐
相关产品推荐

