React Hook Form:实现至少一个输入框非空的验证难题
解决React Hook Form中至少填写一个输入框的验证问题
你的问题核心在于字段级验证函数默认仅能获取当前字段的值,无法跨字段校验,导致两个输入框被单独要求非空。要实现“至少填一个”的逻辑,需让验证函数能访问整个表单的所有值,具体方案如下:
步骤1:定义表单值类型(可选但推荐)
先明确表单数据类型,避免类型错误:
type FormInputs = { phoneNumber: string; email: string; };
步骤2:编写跨字段验证函数
验证函数接收两个参数:当前字段的值,以及整个表单的所有值。仅当两个输入框都为空时返回错误信息,否则返回true:
const atLeastOneFilled = (value: string, formValues: FormInputs) => { if (!formValues.phoneNumber.trim() && !formValues.email.trim()) { return '手机号或邮箱至少填写一个'; } return true; };
步骤3:在Controller中绑定验证函数
给两个Controller的验证规则都绑定这个函数,确保跨字段校验生效:
<Controller control={control} name="phoneNumber" rules={{ validate: atLeastOneFilled }} render={({ field, fieldState: { error } }) => ( <TextField {...field} label="Phone Number" error={!!error} helperText={error?.message} /> )} /> <Controller control={control} name="email" rules={{ validate: atLeastOneFilled }} render={({ field, fieldState: { error } }) => ( <TextField {...field} label="Email" error={!!error} helperText={error?.message} /> )} />
为什么之前的尝试会报错?
你之前给验证函数传入Inputs或string[]类型,不符合React Hook Form字段级验证函数的签名要求。字段级验证函数的第一个参数是当前字段的值(对应字段的类型,比如这里是string),第二个参数是整个表单的values对象,必须匹配这个签名才能通过类型检查。
额外优化:表单级验证(可选)
若不想给每个字段单独加验证,也可在useForm配置中设置表单级验证,提交时一次性校验:
const { control, handleSubmit, formState: { errors } } = useForm<FormInputs>({ mode: 'onSubmit', defaultValues: { phoneNumber: '', email: '' }, resolver: async (values) => { const errors: Partial<Record<keyof FormInputs, string>> = {}; if (!values.phoneNumber.trim() && !values.email.trim()) { errors.phoneNumber = '手机号或邮箱至少填写一个'; errors.email = '手机号或邮箱至少填写一个'; } return { values, errors }; }, });
内容的提问来源于stack exchange,提问作者J.Cart
相关产品推荐
相关产品推荐

