7

在处理 React-hook-form 时进行输入字段匹配验证的最佳实践是什么?例如,匹配email输入时等。

在使用 React-hook-form 研究电子邮件匹配验证时,在尝试通过其验证方法将错误消息与“耦合元素”分开时发现了一个问题。唯一需要一个ref参数用于 React-hook-form register,同时需要用于useRef访问current.valuefor 值匹配,如下:

import React, { useRef } from "react";
import ReactDOM from "react-dom";
import { useForm } from "react-hook-form";

function App() {
  const { register, handleSubmit, errors } = useForm();
  const inputEmail = useRef(null)
  const onSubmit = data => {
    console.log('onSubmit: ', JSON.stringify(data))
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <label htmlFor="email">Email</label>
      <input
        name="email"
        type="email"
        ref={inputEmail}
      />
      {/* desired: show `email` error message */}
      <label htmlFor="email">Email confirmation</label>
      <input
        name="emailConfirmation"
        type="email"
        ref={register({
          validate: {
            emailEqual: value => (value === inputEmail.current.value) || 'Email confirmation error!',
          }
        })}
      />
      {errors.emailConfirmation && <p>{errors.emailConfirmation.message}</p>}
      <input type="submit" />
    </form>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

虽然在进行输入字段匹配时,这种模式似乎是一种选择,但它不能很好地与 React-hook-form 配合使用!

例如,错误消息仅与一个输入案例耦合,并且没有针对每个独立字段的单独消息,或者输入字段之一没有分配给它的寄存器,这意味着required未设置属性等。

所以,我正在寻找一个好的实践或模式来解决:

  • 保持错误消息由输入字段分隔
  • 验证方法,在测试匹配时应该能够以符合 React 的方式引用双字段值,而不是通过 DOM(document.querySelector 等)
4

2 回答 2

15

您不需要手动参考inputEmail. 相反,使用该getValues方法获取整个表单的当前值。

const { register, getValues } = useForm()

然后您注册两个输入并getValues从您的自定义验证中调用。

  <input
    name="email"
    type="email"
    ref={register}
  />
  <input
    name="emailConfirmation"
    type="email"
    ref={register({
      validate: {
        emailEqual: value => (value === getValues().email) || 'Email confirmation error!',
      }
    })}
  />
于 2020-03-26T18:43:19.147 回答
1

为此,您可以使用Yup库,这很棒:

实例化并传递有效架构时添加validationSchema到您的配置对象。像这样:useFormYup

const Schema = yup.object().shape({
  email: yup.string().required('Required field'),
  emailConfirmation: yup
    .string()
    .oneOf([yup.ref('email')], 'Emails must match')
    .required('Required field'),
});

// How to add it to your useForm
const { register } = useForm({
  validationSchema: Schema
})

您的组件应如下所示:

function App() {
  const { register, handleSubmit, errors } = useForm({
    validationSchema: Schema
  });

  const onSubmit = data => {
    console.log('onSubmit: ', JSON.stringify(data))
  }

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <label htmlFor="email">Email</label>
      <input
        name="email"
        type="email"
        ref={register}
      />
      {/* desired: show `email` error message */}
      <label htmlFor="email">Email confirmation</label>
      <input
        name="emailConfirmation"
        type="email"
        ref={register}
      />
      {errors.emailConfirmation && <p>{errors.emailConfirmation.message}</p>}
      <input type="submit" />
    </form>
  );
}
于 2020-03-26T18:42:59.143 回答