You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:23:11