如何基于外部Checkbox状态用Yup.test()实现表单字段条件校验?
解决方案:基于Checkbox状态的条件必填校验(React Hook Form + Yup)
方法一:使用Yup when() 实现条件校验(推荐)
Yup的when()方法专门处理字段间的条件依赖,比test()更简洁直观,完全适配你的需求:
import { useForm, useWatch } from 'react-hook-form'; import { yupResolver } from '@hookform/resolvers/yup'; import * as Yup from 'yup'; import { useMemo } from 'react'; export default function FileUploadForm() { const { register, handleSubmit, formState: { errors }, control } = useForm({ defaultValues: { isUploadRequired: false, tenderReturnReportPath: null } }); // 监听Checkbox状态变化 const isUploadRequired = useWatch({ control, name: 'isUploadRequired' }); // 定义条件校验Schema const validationSchema = Yup.object().shape({ isUploadRequired: Yup.boolean(), tenderReturnReportPath: Yup.mixed() .when('isUploadRequired', { is: true, // 当Checkbox勾选时 then: (schema) => schema.required('请上传文件'), // 字段设为必填 otherwise: (schema) => schema.notRequired() // 未勾选时跳过校验 }) }); // 缓存resolver,避免状态变化时重复生成 const resolver = useMemo(() => yupResolver(validationSchema), [isUploadRequired]); const onSubmit = (data) => { console.log('提交数据:', data); }; return ( <form onSubmit={handleSubmit(onSubmit)}> <div> <input type="checkbox" {...register('isUploadRequired')} id="upload-check" /> <label htmlFor="upload-check">需要上传文件</label> </div> <div> <input type="file" {...register('tenderReturnReportPath')} disabled={!isUploadRequired} id="file-upload" /> {errors.tenderReturnReportPath && <p className="error">{errors.tenderReturnReportPath.message}</p>} </div> <button type="submit">提交表单</button> </form> ); }
方法二:使用Yup test() 自定义校验逻辑
如果需要更复杂的自定义规则,可以用test()方法,通过this.parent访问表单内的Checkbox状态:
const validationSchema = Yup.object().shape({ isUploadRequired: Yup.boolean(), tenderReturnReportPath: Yup.mixed() .test( 'required-if-checked', // 校验规则唯一标识 '请上传文件', // 错误提示文本 function(value) { // 通过this.parent获取Checkbox的状态 const shouldRequire = this.parent.isUploadRequired; if (shouldRequire) { // 勾选时校验文件是否存在 return value !== null && value !== undefined; } // 未勾选时直接通过校验 return true; } ) });
方法三:直接使用React Hook Form内置校验(无需Yup)
如果校验逻辑简单,完全可以跳过Yup,直接在register中定义validate规则,代码更轻量化:
<input type="file" {...register('tenderReturnReportPath', { validate: (value) => { if (isUploadRequired && !value) { return '请上传文件'; } return true; } })} disabled={!isUploadRequired} id="file-upload" />
关键注意事项
- 用
useWatch监听Checkbox状态,配合useMemo缓存yupResolver,确保状态变化时校验规则同步更新,避免不必要的重渲染。 - 给上传字段添加
disabled={!isUploadRequired},React Hook Form会自动跳过禁用字段的校验,和规则形成双重保障。
内容的提问来源于stack exchange,提问作者Arpita Raj
相关产品推荐
相关产品推荐

