如何使用 React 和 Formik 验证登录表单

介绍

为了确保您的 Web 应用程序的表单元素返回有效的数据,将自动验证构建到您的代码中是有帮助的。

在 React 中,处理和验证表单可能有点复杂,要让您的代码更易于管理,您可以使用类似 Formik的包来构建表单。

在本教程中,您将创建一个 React 项目,添加 Formik 包,自定义 Formik 组件,使用onSubmit召回函数和错误消息的验证函数,然后向用户显示这些错误消息。

在本教程结束时,您将有一个项目,如 CodeSandbox上的这个实时示例

前提条件

步骤1 - 创建项目

使用 Create React App 创建项目. 对于本教程的目的,您可以命名您的项目 validate-react-login-form。

1npx create-react-app validate-react-login-form

您现在可以切换到项目目录,启动节点服务器,并在 Web 浏览器中查看它。

1cd validate-react-login-form
2npm start

如果你安装了yarn,你的消息可能会指示你使用yarn start而不是npm start。如果你更喜欢有npm指令,你可以在创建项目时使用use-npm旗(https://create-react-app.dev/docs/getting-started/#selecting-a-package-manager)。

您也可以在您最喜欢的编辑器中打开该项目目录,以创建和修改文件。

创建 React App 将包含多个文件,但为本教程的目的,您只会直接创建或修改三个文件:index.js、index.css 和 ValidatedLoginForm.js。

步骤2 - 安装依赖性

现在我们已经创建了我们的初始项目,我们将安装三个包: Formik, email-validatorYup

Formik使处理验证、错误消息和形式提交更加易于管理。

在您的终端中,安装 Formik:

1npm install formik

email-validator是一个用于验证电子邮件的小包。

如果您的终端,请安装email-validator:

1npm install email-validator

Yup是与Formik一起常用的方案验证器。

在您的终端上,安装Yup:

1npm install yup

现在你已经安装了必要的包,你已经准备好创建验证表单组件。

步骤 3 – 创建验证表单组件

现在你已经安装了依赖性,你可以开始写你的ValidatedFormComponent。 现在,你将创建基础知识,并将其导入到应用程序中的根文件中,以显示它。

为了做到这一点,你会做以下的事情:

  • 创建新的功能组件
  • 添加模糊的显示内容
  • 将其导入到 index.js

在您的src目录中创建一个名为ValidatedLoginForm.js的新文件。

 1[label src/ValidatedLoginForm.js]
 2import React from "react";
 3
 4const ValidatedLoginForm = () => (
 5  <div>
 6    <h1>Validated Form Component</h1>
 7  </div>
 8);
 9
10export default ValidatedLoginForm;

然后将其添加到您的 index.js 文件中:

1[label src/index.js]
2import ValidatedLoginForm from "./ValidatedLoginForm";

接下来,参考组件:

1[label src/index.js]
2<ValidatedLoginForm />

当你把所有这些零件放在一起时,index.js 将看起来像这样:

 1[label src/index.js]
 2import React from "react";
 3import ReactDOM from "react-dom";
 4
 5import ValidatedLoginForm from "./ValidatedLoginForm";
 6
 7function App() {
 8  return (
 9    <div className="App">
10      <h1>Validated Login Form</h1>
11      <ValidatedLoginForm />
12    </div>
13  );
14}
15
16const rootElement = document.getElementById("root");
17ReactDOM.render(<App />, rootElement);

您将看到显示的表单组件:

Validated Form Component in CodeSandbox

现在,让我们重新浏览验证LoginForm.js来实现Formik。

首先,在新组件中导入 Formik、电子邮件验证器和Yup:

1[label src/ValidatedLoginForm.js]
2import { Formik } from "formik";
3import * as EmailValidator from "email-validator"; // used when validating with a self-implemented approach
4import * as Yup from "yup"; // used when validating with a pre-built solution

现在,让我们用初始值来写 Formik 标签,以初始值为初始状态。

您还需要一个在提交回调。这个回调将需要两个参数,值和一个对象,您可以摧毁。 这些值代表您的表单中的输入值。

在回调中,拨打从第二个参数中被破坏的setSubmiting函数,这将允许您在无同步登录呼叫发生时启用或禁用 Submit按钮:

 1[label src/ValidatedLoginForm.js]
 2  <Formik
 3    initialValues={{ email: "", password: "" }}
 4    onSubmit={(values, { setSubmitting }) => {
 5      setTimeout(() => {
 6        console.log("Logging in", values);
 7        setSubmitting(false);
 8      }, 500);
 9    }}
10  >
11    <h1>Validated Login Form</h1>
12  </Formik>

发送PROPS

Formik 组件使用 render props 来为我们创建的表格提供某些变量和函数。

简而言之, render props 用于将属性传递给组件的儿童元素. 在这种情况下,Formik 会将属性传递给您的表单代码,即孩子。

 1[label src/ValidatedLoginForm.js]
 2    {props => {
 3      const {
 4        values,
 5        touched,
 6        errors,
 7        isSubmitting,
 8        handleChange,
 9        handleBlur,
10        handleSubmit
11      } = props;
12
13      return (
14        <div>
15          <h1>Validated Login Form</h1>
16        </div>
17      );
18    }}

在此时,‘ValidatedLoginForm.js’应该看起来像:

 1import React from "react";
 2
 3import { Formik } from "formik";
 4import * as EmailValidator from "email-validator";
 5import * as Yup from "yup";
 6
 7const ValidatedLoginForm = () => (
 8  <Formik
 9    initialValues={{ email: "", password: "" }}
10    onSubmit={(values, { setSubmitting }) => {
11      setTimeout(() => {
12        console.log("Logging in", values);
13        setSubmitting(false);
14      }, 500);
15    }}
16  >
17    {props => {
18      const {
19        values,
20        touched,
21        errors,
22        isSubmitting,
23        handleChange,
24        handleBlur,
25        handleSubmit
26      } = props;
27
28      return (
29        <div>
30          <h1>Validated Login Form</h1>
31        </div>
32      );
33    }}
34  </Formik>
35);
36
37export default ValidatedLoginForm;

步骤 4 – 显示形式

现在您可以开始写代码来显示表单. 该表单将有两个输入(电子邮件和密码),每个标签和提交按钮。

 1[label src/ValidatedLoginForm.js]
 2    {props => {
 3      const {
 4        values,
 5        touched,
 6        errors,
 7        isSubmitting,
 8        handleChange,
 9        handleBlur,
10        handleSubmit
11      } = props;
12
13      return (
14        <form onSubmit={handleSubmit}>
15
16          <label htmlFor="email">Email</label>
17          <input
18            id="email"
19            name="email"
20            type="text"
21            placeholder="Enter your email"
22          />
23
24          <label htmlFor="password">Password</label>
25          <input
26            id="password"
27            name="password"
28            type="password"
29            placeholder="Enter your password"
30          />
31
32          <button type="submit">
33            Login
34          </button>
35
36        </form>
37      );
38
39    }}

注意到onSubmit正在从附件中调用handleSubmit

此前提到,您可以禁用提交按钮,而用户已经试图登录,您可以通过使用您从以前的赞助程序中摧毁的isSubmitting属性添加此更改:

1[label src/ValidatedLoginForm.js]
2<button type="submit" disabled={isSubmitting}>
3  Login
4</button>

您可以使用以下 CSS 对您的 styles.css 文件:

 1[label src/styles.css]
 2.App {
 3  font-family: sans-serif;
 4}
 5
 6h1 {
 7  text-align: center;
 8}
 9
10form {
11  max-width: 500px;
12  width: 100%;
13  margin: 0 auto;
14}
15
16label,
17input {
18  display: block;
19  width: 100%;
20}
21
22label {
23  margin-bottom: 5px;
24  height: 22px;
25}
26
27input {
28  margin-bottom: 20px;
29  padding: 10px;
30  border-radius: 3px;
31  border: 1px solid #777;
32}
33
34input.error {
35  border-color: red;
36}
37
38.input-feedback {
39  color: rgb(235, 54, 54);
40  margin-top: -15px;
41  font-size: 14px;
42  margin-bottom: 20px;
43}
44
45button {
46  padding: 10px 15px;
47  background-color: rgb(70, 153, 179);
48  color: white;
49  border: 1px solid rgb(70, 153, 179);
50  transition: ease-in-out background-color 250ms, ease-in-out color 250ms;
51}
52
53button:hover {
54  cursor: pointer;
55  background-color: white;
56  color: rgb(70, 153, 179);
57}

此外,在index.js 中导入styles.css

1[label src/index.js]
2import "./styles.css";

步骤 5 – 添加验证消息逻辑

现在让我们验证我们的输入。 第一步是确定我们希望对我们的输入有哪些限制。 让我们从电子邮件开始。

  • 需要
  • 看起来像一个真正的电子邮件

密码输入应该:

  • 需要
  • 至少有八个字符长
  • 至少包含一个数字

我们将涵盖创建这些消息的两种方式,一种是手动和一种是使用Yup。

编写自己的密码验证解决方案

该函数的目的是通过形式的值重复,以任何我们认为合适的方式验证这些值,并返回具有关键值对的错误对象信息

在 Formik 标签中,先添加以下代码,这将总是为电子邮件添加一个无效电子邮件错误。

1[label src/ValidatedLoginForm.js]
2  validate={values => {
3    let errors = {};
4    errors.email = "Invalid email";
5    return errors;
6  }}

现在,您可以确保用户为电子邮件输入了一些东西:

1[label src/ValidatedLoginForm.js]
2  validate={values => {
3    let errors = {};
4    if (!values.email) {
5      errors.email = "Required";
6    } 
7    return errors;
8  }}

然后,您可以通过使用电子邮件验证器包来检查电子邮件是否是有效的电子邮件,这将看起来几乎与电子邮件的同等检查相同:

 1[label src/ValidatedLoginForm.js]
 2  validate={values => {
 3    let errors = {};
 4    if (!values.email) {
 5      errors.email = "Required";
 6    } else if (!EmailValidator.validate(values.email)) {
 7      errors.email = "Invalid email address.";
 8    }
 9    return errors;
10  }}

它会照顾电子邮件,所以你会工作在密码表格上. 你会首先检查用户是否输入一些东西:

1[label src/ValidatedLoginForm.js]
2  validate={values => {
3    let errors = {};
4    if (!values.password) {
5      errors.password = "Required";
6    } 
7    return errors;
8  }}

现在你需要确保长度至少是八个字符:

 1[label src/ValidatedLoginForm.js]
 2  validate={values => {
 3    const passwordRegex = /(?=.*[0-9])/;
 4    if (!values.password) {
 5      errors.password = "Required";
 6    } else if (values.password.length < 8) {
 7      errors.password = "Password must be 8 characters long.";
 8    } 
 9
10    return errors;
11  }}

最后,检查密码是否包含至少一个数字,您可以使用regex:

 1[label src/ValidatedLoginForm.js]
 2  validate={values => {
 3    let errors = {};
 4
 5    const passwordRegex = /(?=.*[0-9])/;
 6    if (!values.password) {
 7      errors.password = "Required";
 8    } else if (values.password.length < 8) {
 9      errors.password = "Password must be 8 characters long.";
10    } else if (!passwordRegex.test(values.password)) {
11      errors.password = "Invalid password. Must contain one number.";
12    }
13
14    return errors;
15  }}

完成的文件将看起来像这样:

 1[label src/ValidatedLoginForm.js]
 2  validate={values => {
 3    let errors = {};
 4    if (!values.email) {
 5      errors.email = "Required";
 6    } else if (!EmailValidator.validate(values.email)) {
 7      errors.email = "Invalid email address.";
 8    }
 9
10    const passwordRegex = /(?=.*[0-9])/;
11    if (!values.password) {
12      errors.password = "Required";
13    } else if (values.password.length < 8) {
14      errors.password = "Password must be 8 characters long.";
15    } else if (!passwordRegex.test(values.password)) {
16      errors.password = "Invalid password. Must contain one number.";
17    }
18
19    return errors;
20  }}

使用第三方密码验证解决方案

您可能已经注意到,我们自己处理验证逻辑会变得有点混乱。您必须手动完成所有检查。Yup可以为您节省部分工作。使用Yup时,您将不再看到验证属性,而是使用validationSchema

让我们从电子邮件开始,这里是使用Yup的同等验证:

1[label src/ValidatedLoginForm.js]
2  validationSchema={Yup.object().shape({
3    email: Yup.string()
4      .email()
5      .required("Required")
6  })}

现在,对于密码:

 1[label src/ValidatedLoginForm.js]
 2  validationSchema={Yup.object().shape({
 3    email: Yup.string()
 4      .email()
 5      .required("Required"),
 6    password: Yup.string()
 7      .required("No password provided.")
 8      .min(8, "Password is too short - should be 8 chars minimum.")
 9      .matches(/(?=.*[0-9])/, "Password must contain a number.")
10  })}

您现在已经探索了验证表单的两种不同的方法,接下来您将更新代码以显示错误消息。

步骤 6 – 显示验证和错误消息

现在我们有创建错误消息的逻辑,我们需要显示它们. 您需要更新您的表单中的输入才能做到这一点。

我们需要更新电子邮件和密码输入的几个属性:

  • onChange
  • onBlur
  • className

将 Render Props 应用到电子邮件字段

让我们开始更新,onChangeonBlur

 1[label src/ValidatedLoginForm.js]
 2<input
 3  id="email"
 4  name="email"
 5  type="text"
 6  placeholder="Enter your email"
 7  value={values.email}
 8  onChange={handleChange}
 9  onBlur={handleBlur}
10/>

然后你可以添加一个有条件的错误类别,如果有任何错误,你可以通过查看错误对象来检查错误。

您还可以检查触摸的属性,以查看用户是否在显示错误消息之前与电子邮件输入进行交互。

 1[label src/ValidatedLoginForm.js]
 2<input
 3  id="email"
 4  name="email"
 5  type="text"
 6  placeholder="Enter your email"
 7  value={values.email}
 8  onChange={handleChange}
 9  onBlur={handleBlur}
10  className={errors.email && touched.email && "error"}
11/>

最后,如果出现错误,您将向用户显示它们。

电子邮件字段的最终结果将是这样的:

 1[label src/ValidatedLoginForm.js]
 2<label htmlFor="email">Email</label>
 3<input
 4  id="email"
 5  name="email"
 6  type="text"
 7  placeholder="Enter your email"
 8  value={values.email}
 9  onChange={handleChange}
10  onBlur={handleBlur}
11  className={errors.email && touched.email && "error"}
12/>
13{errors.email && touched.email && (
14  <div className="input-feedback">{errors.email}</div>
15)}

将 Render Props 应用到密码字段

现在你需要用密码做同样的事情. 这些步骤类似于电子邮件。

密码字段的最终结果将是这样的:

 1[label src/ValidatedLoginForm.js]
 2<label htmlFor="password">Password</label>
 3<input
 4  id="password"
 5  name="password"
 6  type="password"
 7  placeholder="Enter your password"
 8  value={values.password}
 9  onChange={handleChange}
10  onBlur={handleBlur}
11  className={errors.password && touched.password && "error"}
12/>
13{errors.password && touched.password && (
14  <div className="input-feedback">{errors.password}</div>
15)}

第7步:测试验证

现在您的表单已经完成,您已经准备好测试它了. 您可以通过点击按钮开始,而无需输入任何内容。

Validation messages in the login form

现在,我们可以得到更具体的测试消息. 刷新您的页面来做到这一点. 点击电子邮件输入,但不要输入任何东西:

Focusing the email field in the login form

然后,单击远离输入. 您应该看到 **Required**消息出现. 请注意,当页面加载时,此消息不会自动出现. 您只希望在用户与输入交互后显示错误消息。

Email validation error in the login form

现在,开始键入. 你会收到一个消息,即电子邮件不有效。

Invalid email message in the login form

输入有效的电子邮件,并观察您的错误消息消失。

Valid email in the login form

现在,对密码做同样的事情. 点击输入,然后离开,你会得到所需的消息。

The required password message in the login form

然后,开始键入,你会看到长度验证。

Length validation message in the login form

然后,键入不包含数字的八个或更多字符,您将看到 **必须包含数字**消息。

"must contain a number" message in the login form

最后,添加一个数字,错误消息就会消失。

Valid password in the login form

结论

您现在已经在 React 中创建了具有自动验证的表单,使用 Formik 和 Yum。

有关 React 的更多教程,请参阅我们的 React 主题页面

Published At
Categories with 技术
Tagged with
comments powered by Disqus