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

来自菜鸟教程
跳转至:导航、​搜索

介绍

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

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

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

在本教程结束时,您将在 CodeSandbox 上拥有一个类似 this live example 的项目。

先决条件

第 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 flag。 您可以在本教程中使用 yarnnpm

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

Create React App 将包含多个文件,但就本教程而言,您将仅直接创建或修改三个文件:index.jsindex.cssValidatedLoginForm.js

第 2 步 — 安装依赖项

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

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

在您的终端中,安装 Formik:

npm install formik

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

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

npm install email-validator

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

在您的终端中,安装是的:

npm install yup

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

第三步——创建验证表单组件

现在您已经安装了依赖项,您可以开始编写您的 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 文件中:

src/index.js

import ValidatedLoginForm from "./ValidatedLoginForm";

接下来,引用组件:

src/index.js

<ValidatedLoginForm />

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

src/index.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);

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

现在,让我们重温 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 函数。 这将允许您在异步登录调用发生时启用或禁用 [X45X]Submit 按钮:

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 属性添加该更改:

src/ValidatedLoginForm.js

<button type="submit" disabled={isSubmitting}>
  Login
</button>

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

src/styles.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);
}

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

src/index.js

import "./styles.css";

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

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

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

密码输入应:

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

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

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

第一种选择是自己创建我们的验证函数。 该函数的目的是遍历表单的值,以我们认为合适的任何方式验证这些值,并返回一个具有 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 消息弹出。 请注意,当页面加载时,此消息不会自动弹出。 您只想在用户与输入交互后显示错误消息。

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

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

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

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

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

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

结论

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

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