Formik使用详解

news2024/10/7 18:21:34

Formik使用详解

react-formik

1 引言

formik

在现代Web应用程序中,表单是一种不可避免的输入机制,但是处理表单的过程可能会变得非常复杂。Formik是一个React表单库,它的目标是简化表单处理的过程。本文将介绍Formik的主要功能和用途,以及如何使用它来简化React表单的处理。

1.1 介绍Formik

Formik是一个专为React构建的开源表单库。它提供了一个易于使用的API来处理表单状态管理,表单验证以及表单提交。Formik支持React中的所有表单元素和事件,可以很好地与React生态系统中的其他库集成。同时,Formik还提供了一些高级功能,如支持异步验证、字段级别的验证、根据表单状态变化自动计算计算属性等。

1.2 本文目的

本文的目的是介绍如何使用Formik来处理React中的表单,包括如何管理表单状态、如何进行表单验证、如何处理表单提交等。本文还将介绍Formik的高级功能和最佳实践,以及与React生态系统中其他库的集成方法。通过本文,读者将能够理解Formik的使用方法,从而更好地管理React中的表单。

2 Formik基础知识介绍

form

2.1 表单处理

在Web应用程序开发中,表单处理是必不可少的一部分。Formik是一个用于React应用程序的表单处理库,它可以帮助开发者轻松地处理复杂的表单,提高表单的可维护性和可重用性。

2.2 Formik的优势

相较于传统的表单处理方法,Formik具有以下优势:

  1. 状态管理: Formik自动地处理表单状态管理,无需手动编写大量的状态管理逻辑。
  2. 表单验证: Formik提供了易于使用的表单验证工具,可以快速实现表单验证逻辑。
  3. 表单提交: Formik可以方便地处理表单提交,包括异步表单提交和重试机制。
  4. 支持复杂表单: Formik支持处理包括多级嵌套、动态表单、数组表单等多种复杂表单。

3 安装和设置Formik

在本节中,我们将介绍如何安装和设置Formik,并且创建一个简单的表单来演示Formik的基本用法。此外,我们还将探讨Formik的高级特性。
formik

3.1 安装Formik

要使用Formik,我们需要先安装它。我们可以使用npm或yarn安装Formik。在终端中,切换到你的项目目录并运行以下命令:

npm install formik

yarn add formik

这将安装最新版本的Formik包。

3.2 创建表单

接下来,我们将创建一个简单的表单来演示如何使用Formik。我们的表单将有两个字段:一个文本框和一个提交按钮。当用户在文本框中输入一些文本并单击提交按钮时,我们将在控制台上打印输入的值。

为了创建表单,我们需要在我们的React组件中导入Formik和相关组件。然后,我们需要使用Formik组件包装我们的表单元素。Formik组件有一个名为handleSubmit的函数,它在表单提交时被调用。我们可以在这个函数中执行一些操作,例如打印表单数据。
以下是示例代码:

import React from 'react';
import { Formik, Form, Field } from 'formik';

const BasicForm = () => (
  <Formik
    initialValues={{ text: '' }}
    onSubmit={(values) => {
      console.log(values.text);
    }}
  >
    {({ handleSubmit }) => (
      <Form onSubmit={handleSubmit}>
        <Field name="text" />
        <button type="submit">Submit</button>
      </Form>
    )}
  </Formik>
);

export default BasicForm;

在上面的代码中,我们使用了Formik组件,并传入了一些参数,例如initialValuesonSubmitinitialValues表示我们的表单的初始值,而onSubmit是一个回调函数,它在表单提交时被调用。

我们使用Field组件创建了一个文本框,然后使用button元素创建了一个提交按钮。当用户单击提交按钮时,我们将打印文本框中的值。

3.3 使用Formik的高级特性

Formik具有许多高级特性,例如表单验证和嵌套字段。下面是一个演示如何使用这些特性的示例代码:

import React from 'react';
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';

// 定义内部嵌套表单的初始值
const initialValues = {
  name: '',
  email: '',
  phone: '',
  address: {
    street: '',
    city: '',
    state: '',
    zip: ''
  }
};

// 使用Yup定义表单验证规则
const validationSchema = Yup.object({
  name: Yup.string().required('姓名不能为空'),
  email: Yup.string().email('无效的电子邮件地址').required('电子邮件地址不能为空'),
  phone: Yup.string().matches(/^\d{10}$/, '无效的电话号码').required('电话号码不能为空'),
  address: Yup.object({
    street: Yup.string().required('街道不能为空'),
    city: Yup.string().required('城市不能为空'),
    state: Yup.string().required('州不能为空'),
    zip: Yup.string().matches(/^\d{5}$/, '无效的邮政编码').required('邮政编码不能为空')
  })
});

// 渲染表单组件
const SignupForm = () => (
  <Formik
    initialValues={initialValues}
    validationSchema={validationSchema}
    onSubmit={(values, { setSubmitting }) => {
      setTimeout(() => {
        alert(JSON.stringify(values, null, 2));
        setSubmitting(false);
      }, 400);
    }}
  >
    {({ isSubmitting }) => (
      <Form>
        <div>
          <label htmlFor="name">姓名</label>
          <Field type="text" name="name" />
          <ErrorMessage name="name" />
        </div>

        <div>
          <label htmlFor="email">电子邮件</label>
          <Field type="email" name="email" />
          <ErrorMessage name="email" />
        </div>

        <div>
          <label htmlFor="phone">电话号码</label>
          <Field type="tel" name="phone" />
          <ErrorMessage name="phone" />
        </div>

        <div>
          <h3>地址</h3>

          <div>
            <label htmlFor="address.street">街道</label>
            <Field type="text" name="address.street" />
            <ErrorMessage name="address.street" />
          </div>

          <div>
            <label htmlFor="address.city">城市</label>
            <Field type="text" name="address.city" />
            <ErrorMessage name="address.city" />
          </div>

          <div>
            <label htmlFor="address.state"></label>
            <Field type="text" name="address.state" />
            <ErrorMessage name="address.state" />
          </div>

          <div>
            <label htmlFor="address.zip">邮政编码</label>
            <Field type="text" name="address.zip" />
            <ErrorMessage name="address.zip" />
          </div>
        </div>

        <button type="submit" disabled={isSubmitting}>
          提交
        </button>
      </Form>
    )}
  </Formik>
);

export default SignupForm;

这个示例代码展示了如何使用Yup定义表单验证规则,并使用Formik处理表单的嵌套字段。

4 Formik的核心功能

Formik 为表单处理提供了一组核心功能,包括值管理、表单提交、表单重置以及处理验证和错误。在这一部分,我们将深入探讨这些功能。
formik

4.1 值管理

Formik 提供了一种简单的方式来管理表单中的值。通过 values 属性,我们可以访问表单中所有输入框的值。这个属性的值是一个对象,每个属性对应一个输入框的值。例如:

import { Formik } from 'formik';

function MyForm() {
  return (
    <Formik
      initialValues={{ firstName: '', lastName: '', email: '' }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      {({ values, handleChange }) => (
        <form>
          <input name="firstName" value={values.firstName} onChange={handleChange} />
          <input name="lastName" value={values.lastName} onChange={handleChange} />
          <input name="email" value={values.email} onChange={handleChange} />
        </form>
      )}
    </Formik>
  );
}

在这个例子中,我们定义了一个包含三个输入框的表单。initialValues 属性定义了这些输入框的初始值。在 onSubmit 回调函数中,我们可以访问表单中所有输入框的值。在表单的渲染函数中,我们可以通过 valueshandleChange 属性访问和管理这些值。

4.2 表单提交

Formik 提供了一种简单的方式来处理表单的提交。通过 onSubmit 属性,我们可以定义一个回调函数,该函数在表单提交时被调用。例如:

import { Formik } from 'formik';

function MyForm() {
  return (
    <Formik
      initialValues={{ firstName: '', lastName: '', email: '' }}
      onSubmit={(values, { setSubmitting }) => {
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
          setSubmitting(false);
        }, 400);
      }}
    >
      {({ values, handleChange, handleSubmit, isSubmitting }) => (
        <form onSubmit={handleSubmit}>
          <input name="firstName" value={values.firstName} onChange={handleChange} />
          <input name="lastName" value={values.lastName} onChange={handleChange} />
          <input name="email" value={values.email} onChange={handleChange} />
          <button type="submit" disabled={isSubmitting}>
            Submit
          </button>
        </form>
      )}
    </Formik>
  );
}

在这个例子中,我们定义了一个包含三个输入框和一个提交按钮的表单。通过 onSubmit 属性,我们定义了一个回调函数,在表单提交时被调用。在回调函数中,我们可以访问表单中所有输入框的值,并执行提交操作。通过 setSubmitting 函数,我们可以设置表单的提交状态。

在表单的渲染函数中,我们通过 handleSubmit 属性来处理表单的提交。我们还使用isSubmitting属性来禁用提交按钮,直到表单提交完成。

4.3 表单重置

Formik表单重置的功能非常有用,可以让用户在重新填写表单时方便地重置表单。重置表单后,表单将恢复到其初始状态,所有字段的值都将被清除。

为了实现这个功能,我们可以在Formik的表单中使用resetForm函数。该函数可以将表单重置为其初始值,并清除任何错误消息和提交状态。我们可以将resetForm函数传递给一个按钮或链接,以便在用户单击该按钮或链接时触发表单重置。

以下是一个示例代码,演示如何在React组件中使用Formik的resetForm函数来重置表单:

import React from 'react';
import { Formik, Field, Form, ErrorMessage } from 'formik';
import * as Yup from 'yup';

const SignupForm = () => {
  return (
    <Formik
      initialValues={{
        firstName: '',
        lastName: '',
        email: '',
      }}
      validationSchema={Yup.object().shape({
        firstName: Yup.string()
          .max(15, 'Must be 15 characters or less')
          .required('Required'),
        lastName: Yup.string()
          .max(20, 'Must be 20 characters or less')
          .required('Required'),
        email: Yup.string()
          .email('Invalid email address')
          .required('Required'),
      })}
      onSubmit={(values, { setSubmitting }) => {
        setTimeout(() => {
          alert(JSON.stringify(values, null, 2));
          setSubmitting(false);
        }, 400);
      }}
    >
      {({ isSubmitting, resetForm }) => (
        <Form>
          <label htmlFor="firstName">First Name</label>
          <Field type="text" name="firstName" />
          <ErrorMessage name="firstName" />

          <label htmlFor="lastName">Last Name</label>
          <Field type="text" name="lastName" />
          <ErrorMessage name="lastName" />

          <label htmlFor="email">Email Address</label>
          <Field type="email" name="email" />
          <ErrorMessage name="email" />

          <button type="submit" disabled={isSubmitting}>
            Submit
          </button>
          <button type="button" onClick={resetForm}>
            Reset
          </button>
        </Form>
      )}
    </Formik>
  );
};

export default SignupForm;

在上面的代码中,我们定义了一个SignupForm组件,它使用了FormikYup库来实现表单验证和处理。表单中有三个字段:firstName、lastName和email。我们还定义了一个按钮来触发表单提交,以及一个按钮来重置表单。当用户单击重置按钮时,resetForm函数将被调用,表单将被重置为其初始值。

通过这种方式,我们可以轻松地实现Formik表单的重置功能,让用户在重新填写表单时更加便捷。

4.4 动态表单

动态表单是指表单中的字段可以根据用户的输入或其他条件而动态变化。这种情况下,我们需要动态地添加或删除表单字段,并根据用户的输入进行验证。

Formik提供了FieldArray组件来实现动态表单。我们可以通过FieldArrayname属性来指定一个数组类型的表单字段,然后通过render属性来指定如何渲染每个元素。例如,下面的代码实现了一个可以动态添加或删除电子邮件地址的表单:

import { Formik, Form, FieldArray, ErrorMessage } from 'formik';

function DynamicForm() {
  return (
    <Formik
      initialValues={{ emails: [''] }}
      onSubmit={(values, actions) => {
        alert(JSON.stringify(values, null, 2));
        actions.setSubmitting(false);
      }}
    >
      {({ values }) => (
        <Form>
          <FieldArray name="emails">
            {({ remove, push }) => (
              <div>
                {values.emails.map((email, index) => (
                  <div key={index}>
                    <input
                      type="email"
                      name={`emails.${index}`}
                      value={email}
                      onChange={(event) => {
                        const newEmails = [...values.emails];
                        newEmails[index] = event.target.value;
                        push(newEmails);
                      }}
                    />
                    <button type="button" onClick={() => remove(index)}>
                      删除
                    </button>
                  </div>
                ))}
                <button type="button" onClick={() => push('')}>
                  添加电子邮件地址
                </button>
              </div>
            )}
          </FieldArray>
          <button type="submit">提交</button>
        </Form>
      )}
    </Formik>
  );
}

在上面的代码中,我们使用了FieldArray组件来处理动态表单。FieldArray组件的name属性指定了一个数组类型的表单字段emails,然后通过render属性来指定如何渲染每个元素。在每个元素的渲染中,我们将表单的值和控件的事件处理函数绑定在一起,这样当用户输入时,Formik会自动更新表单的值和验证状态。

4.5 嵌套表单

Formik支持嵌套表单,可以在表单中使用另一个表单。这种方法可以很好地组织和处理复杂的表单数据。

要在Formik中使用嵌套表单,我们需要使用FieldArray组件,它可以很方便地处理数组字段。我们可以使用FieldArray组件来处理重复的表单元素,例如多个电子邮件地址或电话号码。

下面是一个使用FieldArray组件的示例代码,它显示了如何使用嵌套表单处理联系人列表:

import React from 'react';
import { Formik, Form, Field, FieldArray } from 'formik';
import * as Yup from 'yup';

const ContactFormSchema = Yup.object().shape({
  contacts: Yup.array().of(
    Yup.object().shape({
      name: Yup.string().required('Name is required'),
      email: Yup.string().email('Invalid email').required('Email is required'),
      phone: Yup.string().required('Phone is required'),
    })
  ),
});

const initialValues = {
  contacts: [
    {
      name: '',
      email: '',
      phone: '',
    },
  ],
};

const ContactForm = () => {
  return (
    <Formik
      initialValues={initialValues}
      validationSchema={ContactFormSchema}
      onSubmit={(values) => console.log(values)}
    >
      {({ values }) => (
        <Form>
          <FieldArray name="contacts">
            {({ push, remove }) => (
              <div>
                {values.contacts.map((contact, index) => (
                  <div key={index}>
                    <Field name={`contacts[${index}].name`} />
                    <Field name={`contacts[${index}].email`} />
                    <Field name={`contacts[${index}].phone`} />
                    <button type="button" onClick={() => remove(index)}>
                      Remove
                    </button>
                  </div>
                ))}
                <button type="button" onClick={() => push({ name: '', email: '', phone: '' })}>
                  Add Contact
                </button>
              </div>
            )}
          </FieldArray>
          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  );
};

export default ContactForm;

在上面的代码中,我们使用FieldArray组件来处理名为“contacts”的数组字段。在render函数中,我们可以使用map()方法来遍历数组,并为每个数组元素创建一个表单。此外,我们还可以使用push()方法来添加一个新的空白联系人表单,使用remove()方法删除一个联系人表单。

需要注意的是,我们在嵌套表单中使用了嵌套命名,例如contacts[${index}].name,以确保表单数据正确地映射到values对象中。

这个示例演示了如何使用FieldArray组件和嵌套命名来处理嵌套表单。这个方法可以让我们轻松地处理复杂的表单数据,并在表单中使用其他组件。

4.6 处理验证和错误

在实际的应用中,表单的验证和错误处理是很重要的。Formik 提供了非常方便的验证机制,并且还能轻松处理错误消息。

处理验证

Formik 提供了一个 validate 属性,它是一个函数,用于验证表单的值。这个函数会在表单值改变时自动调用。

import { Formik } from 'formik';

const validate = values => {
  const errors = {};
  if (!values.email) {
    errors.email = 'Required';
  } else if (
    !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
  ) {
    errors.email = 'Invalid email address';
  }
  return errors;
};

const SignupForm = () => (
  <Formik
    initialValues={{ email: '', password: '' }}
    validate={validate}
    onSubmit={(values, { setSubmitting }) => {
      setTimeout(() => {
        alert(JSON.stringify(values, null, 2));
        setSubmitting(false);
      }, 400);
    }}
  >
    {({
      values,
      errors,
      touched,
      handleChange,
      handleBlur,
      handleSubmit,
      isSubmitting,
      /* and other goodies */
    }) => (
      <form onSubmit={handleSubmit}>
        <input
          type="email"
          name="email"
          onChange={handleChange}
          onBlur={handleBlur}
          value={values.email}
        />
        {errors.email && touched.email && errors.email}
        <input
          type="password"
          name="password"
          onChange={handleChange}
          onBlur={handleBlur}
          value={values.password}
        />
        {errors.password && touched.password && errors.password}
        <button type="submit" disabled={isSubmitting}>
          Submit
        </button>
      </form>
    )}
  </Formik>
);

在上面的代码中,我们定义了一个 validate 函数来验证表单的值。如果表单值不符合要求,就返回一个错误对象。Formik 会在表单值改变时自动调用这个函数,根据返回的错误对象显示错误消息。

错误处理
当表单提交失败时,我们可以使用 setStatussetErrors 函数来处理错误。setStatus 函数用于设置表单提交的状态,比如正在提交、提交成功或提交失败等。setErrors 函数用于设置表单中的错误消息。

import { Formik } from 'formik';

const SignupForm = () => (
  <Formik
    initialValues={{ email: '', password: '' }}
    validate={(values) => {
      const errors = {};
      if (!values.email) {
        errors.email = 'Required';
      } else if (
        !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
      ) {
        errors.email = 'Invalid email address';
      }
      return errors;
    }}
    onSubmit={(values, { setSubmitting, setStatus, setErrors }) => {
      axios.post('/api/signup', values)
        .then(response => {
          setSubmitting(false);
          setStatus(response.data.message);
        })
        .catch(error => {
          setSubmitting(false);
          setErrors(error.response.data.errors);
       }}

更复杂高级的form验证代码

import React from 'react';
import { Formik, Form, Field, ErrorMessage } from 'formik';

function SignupForm() {
  const initialValues = {
    firstName: '',
    lastName: '',
    email: '',
    password: '',
    confirmPassword: '',
    acceptTerms: false
  };

  const validate = (values) => {
    const errors = {};

    if (!values.firstName) {
      errors.firstName = 'Required';
    }

    if (!values.lastName) {
      errors.lastName = 'Required';
    }

    if (!values.email) {
      errors.email = 'Required';
    } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)) {
      errors.email = 'Invalid email address';
    }

    if (!values.password) {
      errors.password = 'Required';
    } else if (values.password.length < 8) {
      errors.password = 'Password must be at least 8 characters long';
    }

    if (values.password !== values.confirmPassword) {
      errors.confirmPassword = 'Passwords do not match';
    }

    if (!values.acceptTerms) {
      errors.acceptTerms = 'Required';
    }

    return errors;
  };

  const handleSubmit = (values, { setSubmitting }) => {
    setTimeout(() => {
      alert(JSON.stringify(values, null, 2));
      setSubmitting(false);
    }, 400);
  };

  return (
    <Formik initialValues={initialValues} validate={validate} onSubmit={handleSubmit}>
      {({ isSubmitting }) => (
        <Form>
          <div>
            <label htmlFor="firstName">First Name</label>
            <Field type="text" name="firstName" />
            <ErrorMessage name="firstName" component="div" className="error-message" />
          </div>

          <div>
            <label htmlFor="lastName">Last Name</label>
            <Field type="text" name="lastName" />
            <ErrorMessage name="lastName" component="div" className="error-message" />
          </div>

          <div>
            <label htmlFor="email">Email</label>
            <Field type="email" name="email" />
            <ErrorMessage name="email" component="div" className="error-message" />
          </div>

          <div>
            <label htmlFor="password">Password</label>
            <Field type="password" name="password" />
            <ErrorMessage name="password" component="div" className="error-message" />
          </div>

          <div>
            <label htmlFor="confirmPassword">Confirm Password</label>
            <Field type="password" name="confirmPassword" />
            <ErrorMessage name="confirmPassword" component="div" className="error-message" />
          </div>

          <div>
            <Field type="checkbox" name="acceptTerms" />
            <label htmlFor="acceptTerms">I accept the terms and conditions</label>
            <ErrorMessage name="acceptTerms" component="div" className="error-message" />
          </div>

          <button type="submit" disabled={isSubmitting}>Submit</button>
        </Form>
      )}
    </Formik>
  );
}

export default SignupForm;

在React应用中,Formik是一个非常强大的表单处理库,可以方便地管理表单的状态,验证表单的输入并处理表单的提交。在本文中,我们将介绍Formik的基础知识、安装和设置、核心功能以及高级特性,并提供详细的示例代码。

5 使用Yup进行表单验证

在前面的部分中,我们已经介绍了如何使用Formik进行表单处理。现在,我们将介绍如何使用Yup来验证表单。
formik

5.1 什么是Yup?

Yup是一个轻量级的JavaScript模式验证库,它允许您定义强大的模式,并且易于使用。它可以与任何JavaScript库一起使用,包括React和Formik。

使用Yup,您可以轻松地定义表单字段应满足的要求,例如必填字段、最小/最大值、字符串格式、日期格式等等。

5.2 在Formik中使用Yup

在Formik中使用Yup非常容易。首先,您需要安装Yup:

npm install yup

然后,您需要导入Yup并定义一个模式。下面是一个简单的模式,用于验证电子邮件地址:

import * as Yup from 'yup';

const SignupSchema = Yup.object().shape({
  email: Yup.string().email('Invalid email').required('Required'),
});

在这个模式中,我们定义了一个名为SignupSchema的对象,它具有一个名为email的字符串属性。我们使用Yup.string()方法定义了字符串属性,然后使用Yup.email()方法验证电子邮件格式是否正确,并使用Yup.required()方法验证该字段是否为必填字段。

要在Formik中使用这个模式,只需将其传递给initialValuesvalidationSchema props即可:

<Formik
  initialValues={{ email: '' }}
  validationSchema={SignupSchema}
  onSubmit={(values, actions) => {
    // 处理提交
  }}
>
  {({ errors, touched, handleSubmit, handleChange, values }) => (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        name="email"
        value={values.email}
        onChange={handleChange}
      />
      {errors.email && touched.email && <div>{errors.email}</div>}
      <button type="submit">Submit</button>
    </form>
  )}
</Formik>

在这个示例中,我们将SignupSchema传递给validationSchema props,并使用Yup.object().shape()方法来定义模式。我们还使用initialValues props将email设置为空字符串。在表单中,我们使用Yup.string()Yup.required()方法来验证电子邮件地址,并在需要时显示错误消息。

6 处理复杂的表单需求

在实际开发中,我们经常会遇到需要处理复杂表单需求的情况,比如包含表单数组或动态添加和删除表单域等。Formik提供了一些方便的方法来处理这些需求。
formik

6.1 使用表单数组

表单数组是指表单中包含多个相同的域,例如多个输入框、复选框或下拉列表等。对于这种情况,Formik提供了一个Array Field组件,可以方便地处理表单数组。下面是一个使用Array Field组件的示例代码:

import { FieldArray } from 'formik';

function MyForm() {
  return (
    <Formik
      initialValues={{ users: [{ name: '', email: '' }] }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      {({ values }) => (
        <Form>
          <FieldArray name="users">
            {({ insert, remove, push }) => (
              <div>
                {values.users.map((user, index) => (
                  <div key={index}>
                    <label htmlFor={`users.${index}.name`}>Name</label>
                    <Field name={`users.${index}.name`} type="text" />
                    <label htmlFor={`users.${index}.email`}>Email</label>
                    <Field name={`users.${index}.email`} type="email" />
                    <button type="button" onClick={() => remove(index)}>
                      Remove
                    </button>
                  </div>
                ))}
                <button type="button" onClick={() => push({ name: '', email: '' })}>
                  Add User
                </button>
              </div>
            )}
          </FieldArray>
          <button type="submit">Submit</button>
        </Form>
      )}
    </Formik>
  );
}

在这个示例代码中,我们使用了FieldArray组件来处理名为users的表单数组。我们可以使用map方法来遍历数组,并为每个数组项渲染一个输入框和删除按钮。同时,我们还使用了push方法来添加新的数组项。

6.2 动态添加和删除表单域

在 Formik 中使用表单数组可以帮助我们轻松地处理复杂表单需求。例如,假设我们需要让用户输入他们所有的电话号码,而不仅仅是一个电话号码。这时候,我们可以使用一个表单数组来动态添加和删除电话号码输入框。

下面是一个简单的示例代码,演示了如何使用表单数组。

import React from 'react';
import { Formik, Field, FieldArray } from 'formik';
import * as Yup from 'yup';

const SignupForm = () => (
  <div>
    <h1>Signup Form</h1>
    <Formik
      initialValues={{ phoneNumber: [''] }}
      validationSchema={Yup.object().shape({
        phoneNumber: Yup.array().of(Yup.string().required('Phone number is required')),
      })}
      onSubmit={values => {
        console.log(values);
      }}
      render={({ values }) => (
        <form onSubmit={handleSubmit}>
          <FieldArray name="phoneNumber">
            {({ push, remove }) => (
              <div>
                {values.phoneNumber.map((phoneNumber, index) => (
                  <div key={index}>
                    <Field name={`phoneNumber.${index}`} />
                    {index > 0 && (
                      <button type="button" onClick={() => remove(index)}>
                        Remove
                      </button>
                    )}
                  </div>
                ))}
                <button type="button" onClick={() => push('')}>
                  Add Phone Number
                </button>
              </div>
            )}
          </FieldArray>
          <button type="submit">Submit</button>
        </form>
      )}
    />
  </div>
);

export default SignupForm;

在上面的代码中,我们使用了 FieldArray 组件来创建一个表单数组。在表单数组中,我们可以使用 map 方法来遍历数组中的每个元素,并为每个元素创建一个表单域。我们还可以使用 pushremove 方法来添加和删除表单数组中的元素。

我们还可以使用 FieldArray 组件的 render 方法来自定义表单数组的渲染方式。在上面的代码中,我们将 pushremove 方法作为 FieldArray 的子组件传递,这样我们就可以在点击“Add Phone Number”按钮时添加一个新的电话号码输入框,并在每个电话号码输入框后面添加一个“Remove”按钮,以便用户可以删除电话号码输入框。

除了使用表单数组之外,我们还可以使用 Formik 的 FieldArray 组件处理动态添加和删除表单域的需求。

下面是一个使用FieldArray的示例代码:

import React from 'react';
import { Formik, Form, Field, FieldArray } from 'formik';
import * as Yup from 'yup';

const SignupForm = () => (
  <Formik
    initialValues={{
      name: '',
      email: '',
      phones: ['']
    }}
    validationSchema={Yup.object({
      name: Yup.string()
        .required('Required'),
      email: Yup.string()
        .email('Invalid email address')
        .required('Required'),
      phones: Yup.array()
        .of(Yup.string()
          .matches(/^\d{10}$/, 'Invalid phone number')
        )
    })}
    onSubmit={(values, { setSubmitting }) => {
      setTimeout(() => {
        alert(JSON.stringify(values, null, 2));
        setSubmitting(false);
      }, 400);
    }}
  >
    {({ values }) => (
      <Form>
        <label htmlFor="name">Name</label>
        <Field name="name" type="text" />
        <label htmlFor="email">Email</label>
        <Field name="email" type="email" />
        <FieldArray name="phones">
          {({ insert, remove, push }) => (
            <div>
              {values.phones.length > 0 &&
                values.phones.map((phone, index) => (
                  <div key={index}>
                    <Field name={`phones.${index}`} />
                    {index > 0 && (
                      <button type="button" onClick={() => remove(index)}>Remove</button>
                    )}
                  </div>
                ))}
              <button type="button" onClick={() => push('')}>Add Phone Number</button>
            </div>
          )}
        </FieldArray>
        <button type="submit">Submit</button>
      </Form>
    )}
  </Formik>
);

在上面的示例代码中,我们使用了FieldArray组件来为表单中的电话号码创建一个动态数组。该数组的每个元素都是一个字符串类型的电话号码。在validation Schema中,我们使用了Yup.array()方法来验证该数组的值。如果验证失败,则会出现错误消息。在渲染表单时,我们可以使用map函数来为数组中的每个元素创建一个嵌套表单,并使用insertremove方法来添加和删除元素。

7.结论

formik

7.1 总结Formik的优势和核心功能

Formik提供了许多优秀的特性,使得表单处理变得更加简单。其中一些特性包括:

  • 通过集中管理值,降低了表单处理的复杂性。
  • 提供了自动表单提交和验证机制。
  • 提供了可自定义的表单错误处理机制。
  • 提供了可自定义的表单验证机制,允许开发人员使用自己喜欢的验证库。

Formik的核心功能包括值管理、表单提交、表单重置、处理验证和错误。这些功能可以帮助开发人员管理表单,让表单处理变得更加容易和高效。

7.2 下一步行动

如果你对Formik感兴趣,可以尝试以下操作:

  • 访问Formik官方文档,学习更多关于Formik的知识和用法。
  • 将Formik应用到你的项目中,体验其便利性。
  • 在处理复杂表单时,尝试使用Formik的高级特性,如表单数组和动态表单域。
  • 将Yup或其他验证库集成到Formik中,增强表单验证的能力。

总之,Formik是一个功能强大的表单处理库,它提供了许多方便的功能和工具,帮助开发人员更轻松地处理表单。无论是简单表单还是复杂表单,Formik都能够满足你的需求,提高开发效率和代码质量。

formik

8 参考文献

本文参考了以下资料:

Formik documentation.
https://formik.org/docs/overview

Formik with React Tutorial.
https://www.robinwieruch.de/react-formik

Using Formik to handle forms in React.
https://blog.logrocket.com/using-formik-to-handle-forms-in-react/

Formik – Elegant React forms.
https://rangle.io/blog/formik-elegant-forms-in-react/

Yup documentation.
https://github.com/jquense/yup

Building Reusable Forms with Formik and Yup.
https://rangle.io/blog/building-a-reusable-form-with-formik-and-yup/

Handling Complex Forms in React Using Formik, Yup and Field Arrays. https://www.digitalocean.com/community/tutorials/handling-complex-forms-in-react-using-formik-yup-and-field-arrays

这些资料包括官方文档、教程、博客文章和社区贡献的代码示例,提供了广泛的Formik使用和实践经验。读者可以深入了解Formik的优势、核心功能、高级特性和最佳实践,以及使用Yup进行表单验证和处理复杂表单需求的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/495945.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么成为一名架构师?架构师第一步。基层开发人员逆袭成为架构师真的很难吗?

文章目录 写在前面一、企业需要什么样的架构师1、从招聘软件上了解2、架构师的主要职责与能力 二、成为一名架构师很难吗1、架构师的定义2、当前大部分开发团队的现状3、为什么要有架构师4、技术人员如何自我突破 三、晨钟暮鼓的几句话 写在前面 一个团队中&#xff0c;每个人…

JAVA基础:Scanner类中next(), nextLine(), hasNext(), hasNextLine()

一、next() : 只读缓冲区中空格之前的数据,并且光标指向本行。二、nextLine() : 读取除回车以外的所有符号(整行内容)&#xff0c;光标定位在下一行三、hasNext() &#xff1a;检查下一个标记&#xff08;token&#xff09;&#xff0c;也就是以空格、制表符或换行符为分隔符的…

[JAVA EE]创建Servlet——实现Servlet接口笔记1

创建Servlet的方式之一&#xff1a;实现servlet接口 servlet的生命周期&#xff1a; 1、实例化&#xff1a;创建servlet实例对象 2、初始化&#xff1a;调用init方法完成初始化工作 3、服务&#xff1a;调用service方法来处理用户请求 4、销毁&#xff1a;调用destroy方法…

Java算法比赛常用方法

1. 开方&#xff1a;Math.sqrt(x); 2. x的a方&#xff1a;Math.pow(x,a); 3. 绝对值&#xff1a;Math.abs(x)&#xff1b; 4. BigInteger&#xff1a;大数&#xff08;加&#xff0c;减&#xff0c;乘&#xff0c;除&#xff0c;取余&#xff09; c.add(d) ; c.subtract(d)…

如何用100天彻底学会Python?

Python 是一门功能强大、易于学习且历史悠久的编程语言。如果你希望在短时间内彻底学会 Python&#xff0c;需要制定一个全面的学习计划&#xff0c;并进行刻意的练习和实践。 以下是一份建议的学习计划&#xff0c;帮助你在 100 天内掌握 Python 技能。 第 1-10 天&#xff…

从bootamition出发分析OpenHarmony下Gralloc buffer管理机制

从bootamition出发分析OpenHarmony下Gralloc buffer管理机制 引言 这个文档主要记录从bootamition角度出发&#xff0c;分析OpenHarmony下对gralloc buffer的管理&#xff01;由于OpenHarmony图形子系统过于复杂&#xff0c;且个人由于能力有限&#xff0c;这里我仅从gralloc b…

2023.03青少年机器人技术等级考试理论综合试卷(五级)

2023年3月青少年机器人技术等级考试理论综合试卷&#xff08;五级&#xff09; 一、单选题(共 20 题&#xff0c;共 80 分) 1. 0x35 & 7 的结果是&#xff1f;&#xff08;A &#xff09; A. 5 B. 55 C. 50 D. 54 2.一般状况下&#xff0c;关于主控板的工作电压&#xff0c…

「 Redis 」大key对持久化有什么影响?

「 Redis 」大key对持久化有什么影响&#xff1f; 参考&鸣谢 Redis 大 Key 对持久化有什么影响&#xff1f; XiaoLinCoding 解决了Redis大key问题&#xff0c;同事们都夸他牛皮 大白斯基 快手面试官&#xff1a;Redis变慢了&#xff0c;如何快速排查&#xff1f; Java 那些…

Vue 2.0 学习笔记

Vue学习笔记 文章目录 Vue学习笔记[toc]一、数据代理实现二、事件相关1.事件修饰符2.键盘事件 三、计算属性与监视1.计算属性-computed2.监视-watch 四、条件渲染1.v-show2.v-if&#xff0c;v-else-if 五、循环遍历1.v-for语法2.key的作用与原理 六、内置指令1.v-cloak指令&…

使用GitHub分享项目

一、注册账户 访问GitHub网站&#xff0c;点击“Sign up”按钮开始注册账号。然后按照提示输入你的用户名、电子邮箱地址和密码&#xff0c;提交成功后通过邮箱或你注册的手机号码进行验证身份。 二、上传项目 想分享自己的项目&#xff0c;首先需要在GitHub上创建一个新的仓库…

React + ts学习笔记

前提准备&#xff1a; 环境配置 安装node.js 官网安装&#xff1a;当前使用版本18.15.0 安装新的react应用&#xff1a; 运行命令新建react-app npx create-react-app study-ts-app当前版本&#xff1a; “react”: “^18.2.0”,“react-dom”: “^18.2.0”, 如果出现如…

优维低代码实践:第一个微应用

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 优维…

vue-element-admin踩坑合集+完整包(项目源码 +依赖)

目录 Nodejs版本&#xff1a; 安装依赖时遇到的报错&#xff1a; 启动报错&#xff1a; vue-element-admin完整包地址&#xff1a; 在部署安装使用vue-element-admin开源项目的时候&#xff0c;会遇到各种各样的问题。 这里是本人遇到的一些坑。。。。。。 Nodejs版本&am…

【技术碎片】【Java】计算椭圆的外接矩形坐标

目录 前言原生实现&#xff08;错误方法&#xff09;精确实现&#xff08;数学解&#xff09;参考 前言 遇到一个需要计算一般椭圆&#xff08;斜椭圆&#xff09;的外接矩形坐标的问题&#xff0c;在此记录一下 已知椭圆的中心点坐标centerX centerY&#xff0c;椭圆的长轴&…

FPGA - 7系列 FPGA内部结构之CLB -02- CLB功能详解

前言 本文翻译自UG474第二章&#xff0c;主要对7系列FPGAs CLB结构进行详细介绍。这些细节对设计优化和验证很有帮助。 CLB 排列 CLB 在 7 系列 FPGA 中按列排列。 7 系列是基于 ASMBL架构提供的独特柱状方法的第四代产品。ASMBL 架构 Xilinx 创建了高级硅模块块 (ASMBL) 架…

【hello Linux】线程互斥

目录 1. 互斥量mutex 2. 互斥量的接口 2.1 初始化互斥量 2.2 销毁互斥量 2.3 互斥量加锁和解锁 2.4 互斥量实现原理探究 3. 可重入VS线程安全 4. 常见锁概念 5. 多线程抢票系统 Linux&#x1f337; 在介绍线程互斥前&#xff0c;我们先来看几个专业性术语&#xff1a; 【临界资…

边缘计算节点是啥?边缘计算与CDN有什么关系?一文带你了解边缘计算节点BEC

边缘计算节点是基于CDN边缘节点构建&#xff0c;覆盖全国大部分地区&#xff0c;三大运营商全覆盖。将算力下沉到各城市级节点&#xff0c;提供离用户更近的算力资源。 那么可能有些小伙伴会问&#xff0c;CDN也是就近为用户提供服务&#xff0c;边缘计算节点和CDN有什么不同呢…

时序数据利用EEMD_LSTM模型进行预测(Python编程,数据集和代码均在压缩包,解压缩后可以直接运行,数据可以替换为股票数据,交通流量等时序数据)

运行效果(为减少录屏时间&#xff0c;视频中epoch设置为30&#xff0c;改为100效果更佳):利用EEMD_LSTM模型对时序数据进行预测&#xff08;视频中epoch为30&#xff0c;当为100 的时候效果更佳&#xff09;_哔哩哔哩_bilibili 1.数据介绍&#xff1a;以每天为间隔的时序数据 …

达梦:dts工具迁移mysql decimal(65,30)的字段,报精度超出定义

本文旨在分享迁移MySQL decimal字段​​​​​​​时遇到“精度超出定义”问题时&#xff0c;如何理解MySQL和达梦对于decimal 等这一类数值数据类型。 1.了解达梦的数值数据类型定义 ​​​​​​​​​​​​​​NUMERIC 类型 语法&#xff1a;NUMERIC[(精度 [, 标度])]功…

HBase基础

HBase基础 一、初识HBase HBase 是一个面向列式存储的分布式数据库&#xff0c;其设计思想来源于 Google 的 BigTable 论文。HBase 底层存储基于 HDFS 实现&#xff0c;集群的管理基于 ZooKeeper 实现。HBase 良好的分布式架构设计为海量数据的快速存储、随机访问提供了可能&…