React Formik教程系列之一:介绍


在使用React进行开发的时候,如果是简单的表单还好。如果遇到复杂的表单,比如分好几个步骤的表单,联动效果的字段,多层结构的字段等等,就需要一个好的框架的支持了。下面介绍一下:Formik

React Formik组件
React Formik组件

Formik官网:https://formik.org/
Formik GH:https://github.com/jaredpalmer/formik

Formik介绍

Formik是一个专门用于处理Form的React组件。通过Formik,可以管理表单中的数据,进行输入验证,错误提示,以及表单提交。其实上面提到的这些功能通过基本的React也能实现,只不过通过Formik,可以在可扩展性,性能,及实现时的难易度上做出很大的改进。

普通表单的实现

先来看一下基本表单的实现:

JavaScript
<form>
  <label htmlFor='name'>Name</label>
  <input type="text" id="name" name="name"/><br/>

  <label htmlFor="email">Email</label>
  <input type="email" id="email" name="email"/><br/>

  <label htmlFor="age">Age</label>
  <input type="age" id="age" name="age"/><br/>

  <button>Submit</button>
</form>

使用formik

安装formik

bash
npm install formik

如何在React中使用Formik

基本使用:

JavaScript
import React from "react";
import { useFormik } from "formik";

export default function NormalForm() {
  const initialValues = {
    name: "",
    email: "",
    age: 18,
  };
  const onSubmit = values => {
    console.log(values);
  };
  const validate = values => {
    const errors = {
      name: values.name? undefined: 'Name is required.',
      email: /[\w-]+@([\w-]+\.)+[\w-]+/i.test(values.email)? undefined: 'Invalid email.',
      age: (parseInt(values.age) > 0 && parseInt(values.age) < 100)? undefined: 'Age is invalid.',
    }
    console.log(errors);
    return errors;
  };

  const formik = useFormik({
    initialValues,
    onSubmit,
    validate
  });

  return (
    <div>
      <form onSubmit={formik.handleSubmit}>
        <label htmlFor="name">Name</label>
        <input
          type="text"
          id="name"
          name="name"
          onChange={formik.handleChange}
          value={formik.values.name}
        />
        {formik.touched.name && formik.errors.name? formik.errors.name: ''}
        <br />

        <label htmlFor="email">Email</label>
        <input
          type="text"
          id="email"
          name="email"
          onChange={formik.handleChange}
          value={formik.values.email}
        />
        {formik.touched.email && formik.errors.email? formik.errors.email: ''}
        <br />

        <label htmlFor="age">Age</label>
        <input
          type="age"
          id="age"
          name="age"
          onChange={formik.handleChange}
          value={formik.values.age}
        />
        {formik.touched.age && formik.errors.age? formik.errors.age: ''}
        <br />

        <button type="submit">Submit</button>
      </form>
    </div>
  );
}

在使用Formik的时候,需要传递三个参数给useFormik:

  • initialValues: 通过这里实现对表单字段的绑定
  • onSubmit: 实现表单提交功能
  • validate: 实现表单验证

更为复杂的验证规则

在构建较为复杂的表单时,可能一个属性值的合法性取决于另一个属性值。在这个时候,就可以使用以下的方法:

JavaScript
const validate = values => {
  let errors = {};

  if(!values.name) {
    errors.name = 'Name is required.';
  }
  if(!/[\w-]+@([\w-]+\.)+[\w-]+/i.test(values.email)) {
    errors.email = 'Invalid email.'
  }  
  if(!(parseInt(values.age) > 0 && parseInt(values.age) < 100)) {
    errors.age = 'Age is invalid.';
  }
  
  return errors;
};

使用yup进行验证

安装依赖库:

bash
npm install yup

导入并使用:

JavaScript
import * as Yup from 'yup';
// ...
const validationSchema = Yup.object({
  name: Yup.string().required('必填字段.'),
  email: Yup.string().email('错误邮件地址').required('必填字段'),
  age: Yup.number().required('必填字段')
});

const formik = useFormik({
  initialValues,
  onSubmit,
  validationSchema
});

官网:https://github.com/jquense/yup#validation-tests
关于conditional validation的讨论:https://stackoverflow.com/questions/49394391/conditional-validation-in-yup
关于在yup中自定义验证规则的讨论:https://stackoverflow.com/questions/63769152/how-to-get-yup-to-perform-more-than-one-custom-validation

代码的优化

可以看到,在上面代码中,类似的代码在不断重复:

JavaScript
name="name"
onChange={formik.handleChange}
value={formik.values.name}

// ...
name="age"
onChange={formik.handleChange}
value={formik.values.age}

可以使用如下方式进行简化:

JavaScript
{...formik.getFieldProps('age')}

最终版本:

JavaScript
<input
  type="age"
  id="age"
  name="age"
  {...formik.getFieldProps('age')}
/>

关于visited field

设想有一个表单,要求对字段输入即时验证,并即可给出错误提示。假设有30个不同字段。那么设想一下,在刚加载表单的时候,所有字段都为空,可能都无法通过验证。这时肯定不能立刻显示这些字段值非法。否则会吓坏用户的。只有当用户输入了某个字段值之后并把光标切换到其他位置时,才需要进行验证。这时就需要使用Formik中的visited字段功能了。

其实,这些在Formik中都已经做好了,它们都已经被封装在formik.touched这个对象中了:

JavaScript
formik.touched.name

对于某个字段来说,需要增加onBlur处理函数:

JavaScript
<input
  type="age"
  id="age"
  name="age"
  onChange={formik.handleChange}
  onBlur={formik.handleBlue}
  value={formik.values.age}
/>

这样Formik就会维护touched对象的值,一旦某个字段已经被使用过的话,其值为true:

json
{
  name: true
}

文章作者: 逻思
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 逻思 !