使用 react-hook-form 进行表单验证

2025-06-10

使用 react-hook-form 进行表单验证

表单是任何应用程序中必须存在的核心功能之一。此功能允许我们与用户数据(输入)进行交互,并将其处理为有价值的数据或资源(输出)。

尽管这个功能很强大,但它也有一个最大的障碍。没错,就是如何验证用户输入。这就是我写这篇文章的原因。

在本文中,我将与您分享如何使用名为的包在 React 应用程序中专门处理表单验证react-hook-form

让我们开始吧!

要求

  • React 应用程序(全新或现有应用程序)

注意:
我将使用我之前的项目example-app。它没有任何功能。只是一个使用 安装的全新 React 项目CRA

步骤

1. 添加 react-hook-form

我在里面使用 Git example-app。因此,在添加包之前,我会创建一个名为的新分支,feat-signin然后在完成该功能后将其合并到主分支中。

# Create and checkout to branch feat-signin
git checkout -b feat-signin
Enter fullscreen mode Exit fullscreen mode

现在,是时候添加包了。

yarn add react-hook-form
Enter fullscreen mode Exit fullscreen mode

2.创建表单

也许你知道我想构建什么表单。是的,这是一个登录表单。我会在用户真正登录之前验证他们的邮箱和密码。

我不会使用任何样式工具。只用 HTML 来简化和集中注意力 :)。

首先,我想在我的项目中添加一个名为 Signin 的页面。

# Here's my current project
.
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── README.md
├── src
│   ├── App.css
│   ├── App.js
│   ├── App.test.js
│   ├── index.css
│   ├── index.js
│   ├── logo.svg
│   ├── pages
│   │   └── Signin.js
│   ├── reportWebVitals.js
│   └── setupTests.js
└── yarn.lock
Enter fullscreen mode Exit fullscreen mode

创建登录表单并将其导入其中App.js

// pages/Signin.js
function Signin() {
  return (
    <div>
      <form>
        <div>
          <label htmlFor="email">Email</label>
          <input type="email" id="email" />
        </div>
        <div>
          <label htmlFor="password">Password</label>
          <input type="password" id="password" />
        </div>
        <div>
          <button>Signin</button>
        </div>
      </form>
    </div>
  );
}

export default Signin;
Enter fullscreen mode Exit fullscreen mode
// App.js
import Signin from './pages/Signin';

function App() {
  return <Signin />;
}

export default App;
Enter fullscreen mode Exit fullscreen mode

3. 使用 react-hook-form 集成表单

让我们整合之前的表单,以便我们可以收集表单内的所有用户输入。

// pages/Signin.js
import { useForm } from 'react-hook-form';

function Signin() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm();

  const onSubmit = (form) => {
    console.log(form);
  };

  return (
    <div>
      <form onSubmit={handleSubmit(onSubmit)}>
        <div>
          <label htmlFor="email">Email</label>
          <input type="email" id="email" {...register('email')} />
        </div>
        <div>
          <label htmlFor="password">Password</label>
          <input type="password" id="password" {...register('password')} />
        </div>
        <div>
          <button>Signin</button>
        </div>
      </form>
    </div>
  );
}

export default Signin;
Enter fullscreen mode Exit fullscreen mode

运行应用程序,打开浏览器控制台并尝试提交表单。您将看到如下图所示的内容。
提交表单

4.添加输入验证

如果我提交带有空密码的表单,我将不会收到任何表明我忘记输入密码的错误消息,这是一个糟糕的用户体验。
忘记输入密码

为了实现该功能,我们需要安装两个包。@hookform/resolvers/yupyup

yarn add @hookform/resolvers yup
Enter fullscreen mode Exit fullscreen mode

注意:
yup 是 JavaScript 模式对象之一。它允许我们定义形状(结构)并验证 JavaScript 对象。您也可以使用其他模式对象,例如 Joi、Zod 等。

现在,让我们在表单中添加输入验证。

// pages/Signin.js

// ...
import { yupResolver } from '@hookform/resolvers/yup';
import * as yup from 'yup';

const schema = yup.object().shape({
  email: yup.string().email().required(),
  password: yup.string().required(),
});

function Signin() {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm({ resolver: yupResolver(schema) });

// ...
}
// ...
Enter fullscreen mode Exit fullscreen mode

现在,如果我们提交带有空密码的表单,我们将不会在浏览器控制台中看到任何消息,因为表单实际上抛出了错误消息而不是提交表单。
表单错误

看,甚至光标都自动聚焦到产生错误的输入元素上。

5.显示错误消息

现在,表单可以验证输入值了,但这还不够。我们需要显示表单中存在的问题,以便用户输入正确的值。

// pages/Signin.js

<div>
  <label htmlFor="email">Email</label>
  <input type="email" id="email" {...register("email")} />
  {errors.email?.message && <span>{errors.email.message}</span>}
</div>
<div>
  <label htmlFor="password">Password</label>
  <input type="password" id="password" {...register("password")} />
  {errors.password?.message && <span>{errors.password.message}</span>}
</div>
Enter fullscreen mode Exit fullscreen mode

提交表单,我们可以看到错误消息。
带有错误消息的表单

嗯,我觉得错误信息不够友好,对吧?所以,我们来改进一下。

6.自定义错误消息

这就是我选择 Yup 进行模式验证的原因。我们可以轻松地像这样自定义错误消息。

// pages/Signin.js

// ...
const schema = yup.object().shape({
  email: yup
    .string()
    .email('Please provide a valid email address')
    .required('Please provide your email address'),
  password: yup.string().required('Please provide your password'),
});
// ...
Enter fullscreen mode Exit fullscreen mode

再次提交表单,您将看到错误消息已经改变。
改进的错误消息

奖金

仅在客户端验证表单是不够的。我们还需要在服务器端验证表单,因为攻击者可以绕过我们在客户端的验证。

当我们想将服务器的错误信息显示在表单中时,问题就出现了。幸运的是,我们可以使用 react-hook-form 轻松实现此功能。

我们只需要使用setErrorAPI 将来自服务器的错误消息显示到表单中。

// pages/Signin.js

// Response from the server
// {
//   "message": "...",
//   "errors": {
//     email: ["The email must be a valid email address."]
//   }
// }

// ...
const {
  register,
  handleSubmit,
  formState: { errors },
  setError,
} = useForm({ resolver: yupResolver(schema) });

const onSubmit = async (form) => {
  // Do sign-in process. Just example :)
  await Http.post(/** ... */);

  if ((await Http.status()) === 422) {
    let res = await Http.response();

    for (let [field, messages] of Object.entries(res.errors)) {
      setError(field, { type: 'manual', message: message.join(' ') });
    }
  }

  // ...
};
// ...
Enter fullscreen mode Exit fullscreen mode

鏂囩珷鏉ユ簮锛�https://dev.to/thexdev/form-validation-with-react-hook-form-94e
PREV
如何获得技术写作工作、演出或机会
NEXT
✨ 适合每个开发人员的 5 款有用的生产力应用程序!