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

介绍

为了确保您的 Web 应用程序的表单元素返回有效数据,在您的代码中构建自动验证很有帮助。这在 React 中也是如此,因为尽早创建表单验证通常可以避免您在旅途中遇到错误。

在 React 中,处理和验证表单可能有点冗长。为了使您的代码更易于管理,您可以使用Formik 之类的包来构建表单。

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

在本教程结束时,您将在 CodeSandbox 上拥有一个与此实时示例类似的项目

先决条件

步骤 1 — 设置项目

使用 Create React App 创建一个项目。出于本教程的目的,您可以将项目命名为validate-react-login-form

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

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

  • cd validate-react-login-form
  • npm start

如果您已yarn安装,您的消息可能会指示您使用yarn start代替npm start如果您更喜欢有npm说明,可以在创建项目时使用--use-npm标志您可以使用yarnnpm用于本教程。

你也可以在你喜欢的编辑器中打开这个项目目录来创建和修改文件。

创建应用程序做出反应将包括几个文件,但对于本教程的目的,你只会被直接创建或修改三个文件:index.jsindex.css,和ValidatedLoginForm.js

第 2 步 – 安装依赖项

现在,我们有我们最初的项目创建,我们将安装三个包:Formik电子邮件验证,并没错

Formik使处理验证、错误消息和表单提交更易于管理。

在您的终端中,安装 Formik:

  • npm install formik

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

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

  • npm install email-validator

是一个模式验证器,其通常与Formik结合使用。

在您的终端中,安装 Yup:

  • npm install yup

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

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

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

为此,您将执行以下操作:

  • 创建一个新的功能组件
  • 添加虚拟显示内容
  • 将其导入 index.js

在您的src目录中创建一个名为ValidatedLoginForm.js. 在该文件中,添加功能组件的基本代码:

src/ValidatedLoginForm.js
import React from "react";

const ValidatedLoginForm = () => (
  <div>
    <h1>Validated Form Component</h1>
  </div>
);

export default ValidatedLoginForm;

然后,将其包含在您的index.js文件中:

源代码/索引.js
import ValidatedLoginForm from "./ValidatedLoginForm";

接下来,引用组件:

源代码/索引.js
<ValidatedLoginForm />

当您将所有这些部分放在一起时,index.js将如下所示:

源代码/索引.js
import React from "react";
import ReactDOM from "react-dom";

import ValidatedLoginForm from "./ValidatedLoginForm";

function App() {
  return (
    <div className="App">
      <h1>Validated Login Form</h1>
      <ValidatedLoginForm />
    </div>
  );
}

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

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

CodeSandbox 中的验证表单组件

现在,让我们重新审视ValidatedLoginForm.js实现 Formik。

首先,在新组件中导入 Formik、email-validator 和 Yup:

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

现在,让我们用初始值编写 Formik 标签。将初始值视为最初设置您的状态。

您还需要onSubmit回调。此回调将采用两个参数、值和一个对象,您可以对其进行解构。这些值代表表单中的输入值。您将在此处添加一些虚拟代码来模拟异步登录调用,然后注销这些值。

在回调中,调用setSubmitting从第二个参数解构的函数。这将允许您在异步登录调用发生时启用或禁用提交按钮:

src/ValidatedLoginForm.js
  <Formik
    initialValues={{ email: "", password: "" }}
    onSubmit={(values, { setSubmitting }) => {
      setTimeout(() => {
        console.log("Logging in", values);
        setSubmitting(false);
      }, 500);
    }}
  >
    <h1>Validated Login Form</h1>
  </Formik>

渲染道具

Formik 组件使用渲染道具为我们创建的表单提供某些变量和函数。

简而言之,渲染道具用于将属性传递给组件的子元素。在这种情况下,Formik 会将属性传递给您的表单代码,即子代。请注意,您正在使用解构来获取对几个特定变量和函数的引用。

src/ValidatedLoginForm.js
    {props => {
      const {
        values,
        touched,
        errors,
        isSubmitting,
        handleChange,
        handleBlur,
        handleSubmit
      } = props;

      return (
        <div>
          <h1>Validated Login Form</h1>
        </div>
      );
    }}

此时,ValidatedLoginForm.js应该类似于:

import React from "react";

import { Formik } from "formik";
import * as EmailValidator from "email-validator";
import * as Yup from "yup";

const ValidatedLoginForm = () => (
  <Formik
    initialValues={{ email: "", password: "" }}
    onSubmit={(values, { setSubmitting }) => {
      setTimeout(() => {
        console.log("Logging in", values);
        setSubmitting(false);
      }, 500);
    }}
  >
    {props => {
      const {
        values,
        touched,
        errors,
        isSubmitting,
        handleChange,
        handleBlur,
        handleSubmit
      } = props;

      return (
        <div>
          <h1>Validated Login Form</h1>
        </div>
      );
    }}
  </Formik>
);

export default ValidatedLoginForm;

第 4 步 – 显示表单

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

src/ValidatedLoginForm.js
    {props => {
      const {
        values,
        touched,
        errors,
        isSubmitting,
        handleChange,
        handleBlur,
        handleSubmit
      } = props;

      return (
        <form onSubmit={handleSubmit}>

          <label htmlFor="email">Email</label>
          <input
            id="email"
            name="email"
            type="text"
            placeholder="Enter your email"
          />

          <label htmlFor="password">Password</label>
          <input
            id="password"
            name="password"
            type="password"
            placeholder="Enter your password"
          />

          <button type="submit">
            Login
          </button>

        </form>
      );

    }}

请注意,onSubmit正在handleSubmit从道具中调用

早些时候,有人提到您可以在用户已经尝试登录时禁用提交按钮。您现在可以使用isSubmitting从之前的 props 解构属性来添加该更改

src/ValidatedLoginForm.js
<button type="submit" disabled={isSubmitting}>
  Login
</button>

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

源代码/样式.css
.App {
  font-family: sans-serif;
}

h1 {
  text-align: center;
}

form {
  max-width: 500px;
  width: 100%;
  margin: 0 auto;
}

label,
input {
  display: block;
  width: 100%;
}

label {
  margin-bottom: 5px;
  height: 22px;
}

input {
  margin-bottom: 20px;
  padding: 10px;
  border-radius: 3px;
  border: 1px solid #777;
}

input.error {
  border-color: red;
}

.input-feedback {
  color: rgb(235, 54, 54);
  margin-top: -15px;
  font-size: 14px;
  margin-bottom: 20px;
}

button {
  padding: 10px 15px;
  background-color: rgb(70, 153, 179);
  color: white;
  border: 1px solid rgb(70, 153, 179);
  transition: ease-in-out background-color 250ms, ease-in-out color 250ms;
}

button:hover {
  cursor: pointer;
  background-color: white;
  color: rgb(70, 153, 179);
}

此外,进口styles.cssindex.js

源代码/索引.js
import "./styles.css";

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

现在让我们验证我们的输入。第一步是确定我们希望对输入施加哪些约束。让我们从电子邮件开始。电子邮件输入应该:

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

密码输入应该:

  • 需要。
  • 长度至少为八个字符。
  • 至少包含一个数字。

我们将介绍两种创建这些消息的方法,一种是手动创建的,另一种是使用 Yup 的。

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

第一个选项是自己创建我们的验证函数。该功能的目的,通过我们的值是迭代,验证在我们认为合适的任何方式将这些值,并返回一个errors具有的键值对的对象valuemessage

在 Formik 标签内,首先添加以下代码。这将始终Invalid email为电子邮件添加错误。

src/ValidatedLoginForm.js
  validate={values => {
    let errors = {};
    errors.email = "Invalid email";
    return errors;
  }}

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

src/ValidatedLoginForm.js
  validate={values => {
    let errors = {};
    if (!values.email) {
      errors.email = "Required";
    } 
    return errors;
  }}

然后,您可以使用 email-validator 包来检查电子邮件是否是有效的电子邮件。这看起来与等效的电子邮件检查几乎相同:

src/ValidatedLoginForm.js
  validate={values => {
    let errors = {};
    if (!values.email) {
      errors.email = "Required";
    } else if (!EmailValidator.validate(values.email)) {
      errors.email = "Invalid email address.";
    }
    return errors;
  }}

这会处理电子邮件,因此您将处理密码表单。您将首先检查用户是否输入了一些内容:

src/ValidatedLoginForm.js
  validate={values => {
    let errors = {};
    if (!values.password) {
      errors.password = "Required";
    } 
    return errors;
  }}

现在您需要确保长度至少为八个字符:

src/ValidatedLoginForm.js
  validate={values => {
    const passwordRegex = /(?=.*[0-9])/;
    if (!values.password) {
      errors.password = "Required";
    } else if (values.password.length < 8) {
      errors.password = "Password must be 8 characters long.";
    } 

    return errors;
  }}

最后,检查密码是否至少包含一个数字。为此,您可以使用正则表达式:

src/ValidatedLoginForm.js
  validate={values => {
    let errors = {};

    const passwordRegex = /(?=.*[0-9])/;
    if (!values.password) {
      errors.password = "Required";
    } else if (values.password.length < 8) {
      errors.password = "Password must be 8 characters long.";
    } else if (!passwordRegex.test(values.password)) {
      errors.password = "Invalid password. Must contain one number.";
    }

    return errors;
  }}

完成的文件将如下所示:

src/ValidatedLoginForm.js
  validate={values => {
    let errors = {};
    if (!values.email) {
      errors.email = "Required";
    } else if (!EmailValidator.validate(values.email)) {
      errors.email = "Invalid email address.";
    }

    const passwordRegex = /(?=.*[0-9])/;
    if (!values.password) {
      errors.password = "Required";
    } else if (values.password.length < 8) {
      errors.password = "Password must be 8 characters long.";
    } else if (!passwordRegex.test(values.password)) {
      errors.password = "Invalid password. Must contain one number.";
    }

    return errors;
  }}

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

您可能已经注意到,我们自己处理验证逻辑有点冗长。您必须手动进行所有检查。是的,可以为您节省一些工作。使用 Yup 时,您将不再看到该Validate属性,而是使用validationSchema.

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

src/ValidatedLoginForm.js
  validationSchema={Yup.object().shape({
    email: Yup.string()
      .email()
      .required("Required")
  })}

现在,输入密码:

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

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

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

现在我们有了创建错误消息的逻辑,我们需要显示它们。您需要更新表单中的输入才能执行此操作。

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

  • value
  • onChange
  • onBlur
  • className

将渲染道具应用于电子邮件字段

首先让我们来更新valueonChangeonBlur每一个都将使用来自渲染道具的属性:

src/ValidatedLoginForm.js
<input
  id="email"
  name="email"
  type="text"
  placeholder="Enter your email"
  value={values.email}
  onChange={handleChange}
  onBlur={handleBlur}
/>

然后你可以添加一个条件“错误”类,以防出现任何错误。您可以通过查看errors对象来检查错误

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

src/ValidatedLoginForm.js
<input
  id="email"
  name="email"
  type="text"
  placeholder="Enter your email"
  value={values.email}
  onChange={handleChange}
  onBlur={handleBlur}
  className={errors.email && touched.email && "error"}
/>

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

电子邮件字段的最终结果将如下所示:

src/ValidatedLoginForm.js
<label htmlFor="email">Email</label>
<input
  id="email"
  name="email"
  type="text"
  placeholder="Enter your email"
  value={values.email}
  onChange={handleChange}
  onBlur={handleBlur}
  className={errors.email && touched.email && "error"}
/>
{errors.email && touched.email && (
  <div className="input-feedback">{errors.email}</div>
)}

将渲染道具应用于密码字段

现在您需要对密码执行相同操作。这些步骤类似于电子邮件。

密码字段的最终结果将如下所示:

src/ValidatedLoginForm.js
<label htmlFor="password">Password</label>
<input
  id="password"
  name="password"
  type="password"
  placeholder="Enter your password"
  value={values.password}
  onChange={handleChange}
  onBlur={handleBlur}
  className={errors.password && touched.password && "error"}
/>
{errors.password && touched.password && (
  <div className="input-feedback">{errors.password}</div>
)}

步骤 7 — 测试验证

现在您的表单已完成,您可以进行测试了。您可以通过单击按钮开始而不输入任何内容。您将看到验证消息:

登录表单中的验证消息

现在,我们可以更具体地测试消息。刷新您的页面以执行此操作。单击电子邮件输入的内部,但不要输入任何内容:

聚焦登录表单中的电子邮件字段

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

登录表单中的电子邮件验证错误

现在,开始打字。您将收到有关电子邮件无效的消息。

登录表单中的电子邮件无效

输入有效的电子邮件,然后您的错误消息就会消失。

登录表单中的有效电子邮件

现在,对密码执行相同操作。单击输入,然后离开,您将获得所需的消息。

登录表单中所需的密码信息

然后,开始输入,您将看到长度验证。

登录表单中的长度验证消息

然后,键入八个或更多不包含数字的字符,您将看到该must contain a number消息。

登录表单中的“必须包含数字”消息

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

登录表单中的有效密码

结论

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

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

觉得文章有用?

点个广告表达一下你的爱意吧 !😁