使用 Formik +Yup 處理 React 表單驗證

前言

React 操做表單一直都是比較繁瑣的操做,在之前用的是 redux-form, 但如今 formik 這個庫設計得更加優雅,Github 的 star 數目已經遠遠超過 redux-form 了。作表單就是爲了收集一些數據,而後進行提交。而 redux-form 理念是把這些數據存放到 reducer 中去,當咱們表單多的時候,顯然對整個 store 的數據管理不太友好,由於多了不少表單數據。而 formik 解決的其中一個痛點就是這個,它能夠在組件內部處理這些表單項而簡單易用。javascript

Formik 旨在輕鬆管理具備複雜驗證的表單, Formik 支持同步和異步表單級和字段級驗證。css

例子

例子的 Formik 爲 2.1.4 版html

先來看個基本的例子:java

import React from 'react'
import { useFormik } from 'formik'
import './FormDemo.css'

// 檢查表單字段
const validate = values => {
  const errors = {}
  if (!values.name) {
    errors.name = '不能爲空'
  } else if (values.name.length > 20) {
    errors.name = '名字太長,輸入有誤'
  }

  if (!values.email) {
    errors.email = '不能爲空'
  } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
    errors.email = '郵箱格式錯誤'
  }

  return errors
}

const FormDemo = () => {
  const formik = useFormik({
    initialValues: {
      name: '',
      email: '',
    },
    validate,
    onSubmit: values => {
      alert(JSON.stringify(values, null, 2))
    },
  })
  return (
    <form onSubmit={formik.handleSubmit} className='form-wrap'>
      <div className='form-group'>
        <label>名字</label>
        <input
          name='name'
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
          value={formik.values.name}
        />
        {formik.touched.name && formik.errors.name ? (
          <div className='error-tip'>{formik.errors.name}</div>
        ) : null}
      </div>
      <div className='form-group'>
        <label>郵箱</label>
        <input
          name='email'
          onChange={formik.handleChange}
          onBlur={formik.handleBlur}
          value={formik.values.email}
        />
        {formik.touched.email && formik.errors.email ? (
          <div className='error-tip'>{formik.errors.email}</div>
        ) : null}
      </div>

      <button type='submit'>Submit</button>
    </form>
  )
}
export default FormDemo

以上是一個很簡單的表單,輸入名字與郵箱。react

test_formik.gif

上面例子中咱們使用的是 useFormik 這種用法,還有使用 <Formik />withFormik 的用法。git

但咱們發現一個問題,當正在輸入名字的時候,郵箱已經立馬顯示不能爲空了,咱們須要的是當點擊的時候才作其餘表單元素的判斷而不是一次性判斷完。對這一問題,咱們須要再加一個判斷touched, 這個表明表單中的某個字段是否被點擊過,直譯的話就是"觸碰過"或"動過",這樣就不會出現上面的問題了github

{formik.touched.name && formik.errors.name ? (
  <div className='error-tip'>{formik.errors.name}</div>
) : null}

但發現上面的代碼仍是挺多, onChange, onBlur, value 等屬性仍是挺重複的,每一個表單元素寫一段,其實咱們能夠更精簡,使用 formik 裏面的getFieldProps方法redux

<form onSubmit={formik.handleSubmit} className='form-wrap'>
  <div className='form-group'>
    <label>名字</label>
    <input name='name' {...formik.getFieldProps('name')} />
    {formik.touched.name && formik.errors.name ? (
      <div className='error-tip'>{formik.errors.name}</div>
    ) : null}
  </div>
  <div className='form-group'>
    <label>郵箱</label>
    <input name='email' {...formik.getFieldProps('email')} />
    {formik.touched.email && formik.errors.email ? (
      <div className='error-tip'>{formik.errors.email}</div>
    ) : null}
  </div>

  <button type='submit'>Submit</button>
</form>

那麼表單字段的驗證能不能簡化呢?formik 表單驗證大多數咱們會選擇和 yup 庫進行搭配,yup 的專長就是做規則校驗的。用法以下:異步

const formik = useFormik({
    // ...
    validationSchema: Yup.object({
      name: Yup.string().max(20, '名字太長,輸入有誤').required('不能爲空'),
      email: Yup.string().email('郵箱格式錯誤').required('不能爲空'),
    }),
    // ...
  })
  // ...

上面 validationSchema 爲Formik 專門爲 yup 留出的接口,因此 formik 是很好支持 yup 搭配使用的。ui

最後附上官網:https://jaredpalmer.com/formik/

相關文章
相關標籤/搜索