如何在React Hook Form中实现表单跨域验证

704 阅读2分钟

一个跨字段的验证规则是指规则依赖于多个字段。这篇文章介绍了如何在React Hook Form中实现这些类型的验证规则。

React Hook Form Cross-field Validation

一个例子

我们有下面这个表单,可以捕捉到低分和高分:

type Scores = {
  low: number;
  high: number;
};

const ScoreForm = () => {
  const { register, handleSubmit } = useForm<Scores>();

  const onSubmit = (data: Scores) => {
    console.log("data", data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div className="field">
        <label htmlFor="low">Lowest score</label>
        <input type="number" id="low" name="low" ref={register} />
      </div>
      <div className="field">
        <label htmlFor="high">Highest score</label>
        <input type="number" id="high" name="high" ref={register} />
      </div>
      <button type="submit">Save</button>
    </form>
  );
};

这是一个直接的React Hook Form,目前还没有验证规则。

添加简单的验证

分数是强制性的,我们希望它们是在0到10之间。实现这些规则是非常简单的:

const ScoreForm = () => {
  const {
    register,
    handleSubmit,
    errors  } = useForm<Scores>();
  ...
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div className="field">
        <label htmlFor="low">Lowest score</label>
        <input
          type="number"
          id="low"
          name="low"
          ref={register({
            required: true,            min: 0,            max: 10          })}
        />
        {errors.low && errors.low.type === "required" && (          <div className="error">You must enter a score.</div>        )}        {errors.low && errors.low.type === "min" && (          <div className="error">The score must be at least 0.</div>        )}        {errors.low && errors.low.type === "max" && (          <div className="error">The score can't be more than 10.</div>        )}      </div>
      <div className="field">
        <label htmlFor="high">Highest score</label>
        <input
          type="number"
          id="high"
          name="high"
          ref={register({
            required: true,            min: 0,            max: 10          })}
        />
        {errors.high && errors.high.type === "required" && (          <div className="error">You must enter a score.</div>        )}        {errors.high && errors.high.type === "min" && (          <div className="error">The score must be at least 0.</div>        )}        {errors.high && errors.high.type === "max" && (          <div className="error">The score can't be more than 10.</div>        )}      </div>
      <button type="submit">Save</button>
    </form>
  );
};

表单字段现在捕获了0到10之间的低分和高分。

添加跨字段验证

你能发现验证规则中的一个缺口吗?

是的,没错--低分可以比高分更高!我们来实现一个额外的验证规则。

让我们实现一个额外的验证规则,以检查低分不高于高分的情况。这个规则是一个跨字段验证规则的例子,因为它是基于多个字段的--它同时依赖于低分和高分字段。

我们可以通过自定义验证规则在React Hook Form中实现跨字段验证规则。

首先,我们需要将 getValues从React Hook Form。这个函数允许我们访问表单上的任何字段值。我们将需要在我们的自定义验证器函数中使用这个:

const {
  register,
  handleSubmit,
  errors,
  getValues,} = useForm<Scores>();

现在让我们在高分字段上实现自定义验证规则:

<input
  type="number"
  id="high"
  name="high"
  ref={register({
    required: true,
    min: 0,
    max: 10,
    validate: () => Number(getValues("low")) <= Number(getValues("high"))  })}

我们将register 函数的对象参数中的validate 属性设置为一个内联验证器函数。React Hook Form的自定义验证器函数如果通过则返回true ,如果规则失败则返回false 。我们使用getValues 函数来获取验证器函数中的相关字段值。这些字段的值是字符串,所以我们使用 Number构造函数将其转换为数字,然后再进行检查。

很好!

让我们添加验证错误信息:

<input
  type="number"
  id="high"
  ...
/>
...
{errors.high && errors.high.type === "validate" && (  <div className="error">    The highest score can't be less than the lowest score.  </div>)}

type 自定义验证规则错误的属性是 "validate"。

当表单被提交时,验证错误会出现在无效的高分字段旁边:

Validation error message

我们也可以给低分字段添加这个规则,但没有必要。

总结

你可以使用自定义验证规则来实现React Hook Form中的跨域验证。必须使用getValues 函数来获取验证器函数中规则所依赖的字段值。