React Formik教程系列之五:表单验证


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

React Formik组件
React Formik组件

表单验证会在何时运行?

表单验证会在以下几种情况下被触发,进而更新formik.errors对象:

  • 一旦输入字段中的值发生变化时
  • 一旦表单字段失去输入焦点
  • 表单提交时

如果想要当表单字段变化或失去输入焦点时取消表单验证,则可以:

JavaScript
<Formik
  initialValues={initialValues}
  onSubmit={onSubmit}
  validationSchema={validationSchema}
  validateOnChange={false}
  validateOnBlur={false}
>

字段级验证规则

默认情况下,通过传递validationSchema或者validate属性给Formik组件来定义顶级验证规则。其实,还可以针对某个字段来定义字段级验证规则。

什么时候需要使用字段级验证呢?比如:在渲染一个字段的时候,需要调用一个API来获取数据才能渲染,获取完数据后才能进行验证,这是就需要使用字段级别验证了。

定义验证函数

JavaScript
const validateFeedback = value => value? undefined: 'Required';

在字段中使用验证函数

JavaScript
<label htmlFor="feedback">Feedback</label>
<Field
  type="text"
  id="feedback"
  name="feedback"
  validate={validateFeedback}
/>
<ErrorMessage name='feedback'/>

人工控制验证规则

使用顶级的formik对象

类似于Formik组件中的render props,在顶级Formik元素上也可以这样做:

JavaScript
<Formik
  initialValues={initialValues}
  onSubmit={onSubmit}
  validationSchema={validationSchema}>
  { 
    formik => {
      return (
        <Form>
        ......
        </Form>
      )
    }
  }
</Formik>

当需要在整个Form级别做一些操作时,就可以使用formik这个对象了。

人工控制验证逻辑

JavaScript
<button type='button' onClick={() => formik.setTouched({
  name: true,
  age: true,
  feedback: true
})}>访问所有字段</button>
<button type='button' onClick={() => formik.validateForm()}>验证表单</button>

<button type='button' onClick={() => formik.setFieldTouched('feedback')}>使用feedback字段</button>
<button type='button' onClick={() => formik.validateField('feedback')}>验证feedback字段</button>

在Formik中,只有当一些字段被使用过之后,才会显示验证失败后的信息。因此上面需要调用setFieldTouched/setTouched方法来声明某个字段已经被“访问“过了。

使用场景:在用户注册表单中,当用户输入用户名之后,需要调用API检查用户名是否已经存在,然后根据API返回结果显示用户名是否可用。

禁用提交按钮

应用场景:

  • 当表单中有些字段非法时,需要禁用提交按钮
  • 当表单正在提交过程中时,为了避免重复提交,需要禁用提交按钮

表单未通过验证时禁用提交按钮

在前面提到的Formik对象render props中,有一个属性:isValid,用来指示当前表单数据是否合法。

JavaScript
<button type='submit' disabled={ !formik.isValid }>提交</button>

目前有一个小问题,当表单被加载时,由于所有字段都未被访问,因此isValid的初始值为true,其实这个时候是不能提交表单的。

使用validateOnMount在表单加载初期禁用提交按钮

如果想要解决这个问题,第一种方法就是为Formik添加validateOnMount属性,这样在表单加载时就会进行验证:

JavaScript
<Formik 
  initValues={initValues}
  ...
  validateOnMount>
...
</Formik>  

但这种方式仅仅适用于简单表单,当表单过于复杂时,尤其是验证规则过于复杂时,这种方式并不适合。

使用formik.dirty属性

dirty属性反映出表单数据是否被更新。

JavaScript
<button type='submit' disabled={ !(formik.dirty && formik.isValid) }>提交</button>

但这种方式也有一个问题:当表单字段有初始值时,dirty的值就会为false,因此提交按钮将被禁用。

表单提交过程中禁用提交按钮

这时可以使用isSubmitting属性。

JavaScript
<button type='submit' disabled={formik.isSubmitting}>

在默认方式下,提交后formik.isSubmitting的值就会变为false, 同时提交按钮就会被禁用。这是因为Formik无法获取在提交时调用的API何时会返回。

这时可以通过在onSubmit提交函数中控制这个属性:

JavaScript
const onSubmit = (values, onSubmitProps) => {
  onsubmitProps.setSubmitting(false);
}

因此最终的提交按钮代码:

JavaScript
<button type='submit' disabled={!formik.isValid || formik.isSubmitting}>

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