使用React和Formik的无泪形式

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

您编写不包含至少一个表单的 Web 应用程序的情况并不常见。 通常,您的整个应用程序只是一系列表单。 这些表单中的每一个都需要状态管理、事件处理程序,并且通常还需要某种客户端数据验证。 Formik 旨在在一个小包装中完成所有这些工作,并且正如他们所声称的那样,“没有眼泪”。

入门

要开始使用 formik,我们需要通过 npmyarn 将其添加到我们的项目中:

$ npm install --save formik
# or
$ yarn add formik

添加依赖项后,请务必将其导入您将要使用它的项目中。 在本文中,我们将同时使用 FormikForm 辅助组件:

import { Formik, Form } from "formik";

Form 组件是标准 form 元素的包装器,它自动连接附加到 Formik 组件的 onSubmit 处理程序,从而为我们节省更多时间。

Formik 组件

Formik 的真正魔力发生在 Formik 组件中。 该组件将用于包装您的表单并通过渲染道具公开状态值和处理程序。

所述组件可以使用属性来设置我们的默认值、验证提交的值并处理我们的提交。

以下是 Formik 组件如何查找我们稍后将创建的基本登录表单:

<Formik
  // Sets up our default values
  initialValues={{ email: "", password: "" }}

  // Validates our data
  validate={values => {
    const errors = {};

    if (!values.email) errors.email = "Required";

    if (
      !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
    ) {
      errors.email = "You must supply a valid email address";
    }

    if (values.password.length < 8) {
      errors.password = "Passwords must be at least 8 characters";
    }

    if (values.email === values.password) {
      errors.password =
        "Your password shouldn't be the same as your email";
    }

    return errors;
  }}

  // Handles our submission
  onSubmit={(values, { setSubmitting }) => {
    // This is where you could wire up axios or superagent
    console.log("Submitted Values:", values);
    // Simulates the delay of a real request
    setTimeout(() => setSubmitting(false), 3 * 1000);
  }}
>
  {props => (
    <div>This is where your Form and form elements will go!</div>
  )}
</Formik>

如果您熟悉 yupjoi 之类的对象模式验证器,那毫无价值,您可以跳过 validate 属性并传入 validationSchema反而。

表单组件

如前所述,Form 组件是 form 元素的直接替代品,它可以自动连接诸如 onSubmit 处理程序之类的东西。

像往常一样使用它来包装表单的输入:

<Formik>
  {props => (
    <Form>
      <label>My Input</label>
      <input type="text" />
    </Form>
  )}
</Formik>

输入状态

开箱即用,Formik 的渲染属性公开事件处理程序来管理对表单输入的更改,无论它们是否被“触摸”、它们的值和任何错误。

对于整个表单,您将能够判断表单是否处于验证或提交的过程中,以及让您轻松重置表单的事件处理程序。

props.valuesprops.errors 是具有与表单字段对应的属性的对象。

props.handleChangeprops.handleBlur 可以传递给 onChangeonBlur 属性以跟踪更改以及输入是否被“触摸”。

当您只想在用户与元素交互后显示错误而不是在页面加载时(恕我直言,这是首选)时,此“触摸”值会派上用场。

当用户修改表单时,props.dirty 被设置为 true。

状态值 props.isValidatingprops.isSubmitting 让您知道用户处于进程的哪个阶段。 非常适合显示加载程序或禁用表单或单个按钮。

把它放在一起

这是一个带有电子邮件和密码的简单登录表单在正式 Formiked 后的样子:

<Formik
  // Sets up our default values
  initialValues={{ email: "", password: "" }}

  // Validates our data
  validate={values => {
    const errors = {};

    if (!values.email) errors.email = "Required";

    if (
      !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)
    ) {
      errors.email = "You must supply a valid email address";
    }

    if (values.password.length < 8) {
      errors.password = "Passwords must be at least 8 characters";
    }

    if (values.email === values.password) {
      errors.password =
        "Your password shouldn't be the same as your email";
    }

    return errors;
  }}

  // Handles our submission
  onSubmit={(values, { setSubmitting }) => {
    // This is where you could wire up axios or superagent
    console.log("Submitted Values:", values);
    // Simulates the delay of a real request
    setTimeout(() => setSubmitting(false), 3 * 1000);
  }}
>
  {props => (
    <Form>
      <label htmlFor="email">Email</label>
      <div>
        <input
          name="email"
          type="email"
          placeholder="Enter your account email"
          value={props.values.email}
          onChange={props.handleChange}
          onBlur={props.handleBlur}
          style={{
            borderColor:
              props.errors.email && props.touched.email && "red"
          }}
        />
        {props.errors.email && props.touched.email && (
          <div style={{ color: "red" }}>{props.errors.email}</div>
        )}
      </div>
      <label htmlFor="password">Password</label>
      <div>
        <input
          name="password"
          type="password"
          placeholder="Enter your account password"
          value={props.values.password}
          onChange={props.handleChange}
          onBlur={props.handleBlur}
          style={{
            borderColor:
              props.errors.password && props.touched.password && "red"
          }}
        />
        {props.errors.password && props.touched.password && (
          <div style={{ color: "red" }}>{props.errors.password}</div>
        )}
      </div>
      <input
        type="submit"
        value="Submit"
        disabled={props.isSubmitting}
      />
      &nbsp;
      <input
        type="reset"
        value="Reset"
        onClick={props.handleReset}
        disabled={!props.dirty || props.isSubmitting}
      />
    </Form>
  )}
</Formik>

结论

Formik 提供了一种熟悉的、基于 渲染属性 的方法来构建表单。

您通常最终编写的大多数冗余样板和语句管理逻辑都得到了很好的处理,同时仍然提供了足够的动力来对表单进行一些非常复杂的状态管理。

如果您想对本文中的代码进行测试,可以在 CodeSandbox 上查看。

干杯!