加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

使用Formik轻松开发更高质量的React表单(三)<Formik />

发布时间:2020-12-15 20:26:23 所属栏目:百科 来源:网络整理
导读:提醒和建议 根据我的粗浅经验,如果您对Formik感兴趣,并且想深入学习与使用这个库,我建议您还是先对redux-form的使用逻辑与有关概念有所了解,而且理解和使用方面也变得容易得多的多。因为Formik中许多概念与形式与redux-form极其类似,但是各方面都简化了
提醒和建议

根据我的粗浅经验,如果您对Formik感兴趣,并且想深入学习与使用这个库,我建议您还是先对redux-form的使用逻辑与有关概念有所了解,而且理解和使用方面也变得容易得多的多。因为Formik中许多概念与形式与redux-form极其类似,但是各方面都简化了很多,因为它不再依赖于约束整个前面存储的Redux store的限制,由于整个前端使用一个store存储,所以,随着表单数量与形式变得越来越复杂,系统的属性可能会受到严重影响——这是Formik产生的主要原因,Formik干脆不使用Redux,而直接操作React组件,这就有可能使得编写表单元素虽然简单(HTML5)但比较冗长,于是Formik也引入了类似于redux-form的一些API与props等概念(但绝对有区别)。
另外请注意,为了与其他流行的React文章保持一致,有些单词没有必要翻译过来,例如store,values,props,shape,errors,等等。另外,touchtouched这个词在Formik中广泛使用,意思是表单中某个字段被点击过,此时用户可能没有输入什么数据,也有可能输入了新的数据,都称为touched。因此,后面的译文中一般翻译为「动过」,个别地方翻译成「润色」,请理解其使用情形就是。

关于<Formik />组件



<Formik>是一个帮助构建表单的组件,它也使用了类似于当前一些流行的库(如React Motion和 React Router)的render这种prop模式。请参考下面的代码:

import React from ‘react‘;
import { Formik } from ‘formik‘;

const BasicExample = () => (
  <div>
    <h1>My Form</h1>
    <Formik
      initialValues={{ name: ‘jared‘ }}
      onSubmit={(values,actions) => {
        setTimeout(() => {
          alert(JSON.stringify(values,null,2));
          actions.setSubmitting(false);
        },1000);
      }}
      render={props => (
        <form onSubmit={props.handleSubmit}>
          <input
            type="text"
            onChange={props.handleChange}
            onBlur={props.handleBlur}
            value={props.values.name}
            name="name"
          />
          {props.errors.name && <div id="feedback">{props.errors.name}</div>}
          <button type="submit">Submit</button>
        </form>
      )}
    />
  </div>
);

Formik渲染方法



<Formik />这个API共提供了三种渲染方法,它们是:

  • <Formik component>

  • <Formik render>

  • <Formik children>

Formik props列表分析



上面所有三种渲染方法都会传递相同的props。接下来,我们对props每一个分量作相应的解释。

(1)dirty: boolean

当values与初始值不绝对相等时这个属性的值会返回true;否则返回false(Returns true if values are not deeply equal from initial values,false otherwise)。注意:dirty属性是只读的,不应该直接修改它。

下面的API待翻译中......

(2)errors: { [field: string]: string }

其中包含Form校验错误信息。这些信息应当与表单的定义于initialValues中的值(values)保持一致。如果你在使用validationSchema(也推荐你使用),那么数据(原文使用的是“keys and shape”,关于shape一词在React文章中经常见到,这里不便直译)应当与你的模式定义准确匹配。 从内部实现代码来看,Formik会根据你提供的数据转换原始的Yup校验错误信息。如果你在使用validate属性,那么此函数会确定错误对象的具体信息。

handleBlur: (e: any) => void

这是onBlur对应的事件处理器函数。当你需要跟踪某个输入字段是否被“动过”(touched)时很有用。用法比如:<input onBlur={handleBlur} ... />

【注意】本属性仅适用于DOM开发;如果是React Native开发则需使用setFieldTouched代替。

handleChange: (e: React.ChangeEvent<any>) => void

这是一个典型的输入字段内容变化时要触发的事件处理器。当key为事件发出的输入字段的name属性时这一调用会更新values。如果name不存在,那么handleChange函数会进一步查找输入字段(input)的id属性。请注意: 这里的input意指所有HTML input标签。

【注意】本属性仅适用于DOM开发;如果是React Native开发则需使用setFieldValue代替。

handleReset: () => void

这是表单复位处理器函数,调用它将把表单还原到初始值状态。用法比如:<button onClick={handleReset}>...</button>

handleSubmit: (e: React.FormEvent<HTMLFormEvent>) => void

这是表单提交处理器函数。 用法比如:<form onSubmit={props.handleSubmit}>...</form>。请结合本系列文章第一篇中「表单提交原理」部分加以理解。

isSubmitting: boolean

这个属性值代表了表单提交的当前状态。如果表单在提交中将返回true;否则返回false。重要提醒:一旦你尝试提交表单,Formik就会把这个值设置为true。请结合本系列文章第一篇中「表单提交原理」部分加以理解。

isValid: boolean

在不发生错误的情况下这个属性值将为true;或者返回当表单处于pristine条件(例如没有dirty)时会返回isInitialValid的结果值。

isValidating: boolean

如果Formik正在运行任何检验函数,则此属性返回true;否则,返回false。想更多地了解在表单提交过程中isValidating属性发生了什么变化,请结合阅读本系列文章第一篇中「表单提交原理」部分。

resetForm: (nextValues?: Values) => void

强行复位表单。这个调用会清除所有错误及字段「润色」信息,并且设置isSubmitting为false,设置isValidating为false,并且把mapPropsToValues返回值设置为当前的WrappedComponent的props或者是传递过去的参数。注意:当在componentWillReceiveProps内部调用resetForm时,这是很有用的。

setErrors: (fields: { [field: string]: string }) => void

强行设置errors信息。

setFieldError: (field: string,errorMsg: string) => void

强行设置给定字段的error信息。注意,这里的参数field应当匹配你希望更新的errors中的key。这个属性在编写定制的输入错误信息处理器函数时非常有用。

setFieldTouched: (field: string,isTouched: boolean,shouldValidate?: boolean) => void

强行设置给定字段的touched状态值。注意,这里的参数field应当匹配你想更新的「动过」的key。这个属性在编写定制的blur处理器函数时非常有用。如果validateOnBlur的值设置为true(默认即为此值),那么调用这个方法会触发校验运行。你也可以通过传递第三个参数为false来显式地禁止或者跳过校验。

submitForm: () => void

触发表单提交操作。

submitCount: number

Number of times user tried to submit the form. Increases when handleSubmit is called,resets after calling handleReset. submitCount is readonly computed property and should not be mutated directly.

setFieldValue: (field: string,value: any,shouldValidate?: boolean) => void

Set the value of a field imperatively. field should match the key of values you wish to update. Useful for creating custom input change handlers. Calling this will trigger validation to run if validateOnChange is set to true (which it is by default). You can also explicitly prevent/skip validation by passing a third argument as false.

setStatus: (status?: any) => void

Set a top-level status to anything you want imperatively. Useful for controlling arbitrary top-level state related to your form. For example,you can use it to pass API responses back into your component in handleSubmit.

setSubmitting: (isSubmitting: boolean) => void

Set isSubmitting imperatively.

setTouched: (fields: { [field: string]: boolean }) => void

Set touched imperatively.

setValues: (fields: { [field: string]: any }) => void

Set values imperatively.

status?: any

A top-level status object that you can use to represent form state that can‘t otherwise be expressed/stored with other methods. This is useful for capturing and passing through API responses to your inner component.

status should only be modifed by calling setStatus: (status?: any) => void

touched: { [field: string]: boolean }

Touched fields. Each key corresponds to a field that has been touched/visited.

values: { [field: string]: any }

Your form‘s values. Will have the shape of the result of mapPropsToValues (if specified) or all props that are not functions passed to your wrapped component.

validateForm: (values?: any) => void

Imperatively call your validate or [validateSchema] depending on what was specified. You can optionally pass values to validate against and this modify Formik state accordingly,otherwise this will use the current values of the form.

validateField: (field: string) => void

Imperatively call field‘s validate function if specified for given field. Formik will use the current field value.

component

下面给出此属性的典型使用方法:

<Formik component={ContactForm} />;

const ContactForm = ({
  handleSubmit,handleChange,handleBlur,errors,}) => (
  <form onSubmit={handleSubmit}>
    <input
      type="text"
      onChange={handleChange}
      onBlur={handleBlur}
      value={values.name}
      name="name"
    />
    {errors.name && <div>{errors.name}</div>}
    <button type="submit">Submit</button>
  </form>
};

【注意】<Formik component> 的优先级会高于<Formik render>;因此,你不要在同一个<Formik>中同时使用二者。

render: (props: FormikProps<Values>) => ReactNode

这个属性相当重要,请参考如下代码了解其用法:

<Formik render={props => <ContactForm {...props} />} />

<Formik
  render={({ handleSubmit,errors }) => (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        onChange={handleChange}
        onBlur={handleBlur}
        value={values.name}
        name="name"
      />
      {errors.name &&
        <div>
          {errors.name}
        </div>}
      <button type="submit">Submit</button>
    </form>
  )}
/>

children: func

使用方法见下面的代码片断:

&lt;Formik children={props =&gt; &lt;ContactForm {...props} /&gt;} /&gt;

//或者使用下面的方式...

<Formik>
  {({ handleSubmit,errors }) => (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        onChange={handleChange}
        onBlur={handleBlur}
        value={values.name}
        name="name"
      />
      {errors.name &&
        <div>
          {errors.name}
        </div>}
      <button type="submit">Submit</button>
    </form>
  )}
</Formik>

enableReinitialize?: boolean

默认值为false。此属性用于在initialValues变化时控制是否重置表单。

isInitialValid?: boolean

Default is false. Control the initial value of isValid prop prior to mount. You can also pass a function. Useful for situations when you want to enable/disable a submit and reset buttons on initial mount.

initialValues?: Values

Initial field values of the form,Formik will make these values available to render methods component as props.values.

Even if your form is empty by default,you must initialize all fields with initial values otherwise React will throw an error saying that you have changed an input from uncontrolled to controlled.

Note: initialValues not available to the higher-order component,use mapPropsToValues instead.

onReset?: (values: Values,formikBag: FormikBag) => void

Your optional form reset handler. It is passed your forms values and the "FormikBag".

onSubmit: (values: Values,formikBag: FormikBag) => void

Your form submission handler. It is passed your forms values and the "FormikBag",which includes an object containing a subset of the injected props and methods (i.e. all the methods with names that start with set<Thing> + resetForm) and any props that were passed to the the wrapped component.

Note: errors,touched,status and all event handlers are NOT included in the FormikBag.

validate?: (values: Values) => FormikErrors<Values> | Promise<any>

【注意】Formik作用特别推荐我们使用validationSchema和Yup实现表单校验。无论如何,表单校验应该使用一种相对独立的,比较直观的方式实现——这也是每一个所希望的。

另外,你可以使用同步或者异步函数来实现表单校验。请参考下面的代码:

(1)同步校验方式(返回一个errors对象)

// Synchronous validation
const validate = (values,props) => {
  let errors = {};

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

  //...

  return errors;
};

(2)异步校验方式(返回errors对象中的一个代表错误的Promise)

// Async Validation
const sleep = ms => new Promise(resolve => setTimeout(resolve,ms));

const validate = (values,props) => {
  return sleep(2000).then(() => {
    let errors = {};
    if ([‘admin‘,‘null‘,‘god‘].includes(values.username)) {
      errors.username = ‘Nice try‘;
    }
    // ...
    if (Object.keys(errors).length) {
      throw errors;
    }
  });
};

validateOnBlur?: boolean

此属性的默认值为true。你可以在表单blur事件触发时使用这个属性——更具体一些说,无论是调用handleBlur,setFieldTouched还是setTouched都可以。

validateOnChange?: boolean

此属性的默认值为true。当表单触发change事件或者相关事件时你可以使用这个属性告诉Formik进行有关校验。 更具体一些说,无论是调用handleChange,setFieldValue还是setValues都可以。

validationSchema?: Schema | (() => Schema)

这个属性非常重要,用于定义Yup模式( schema)或者是一个返回Yup模式的函数,用于校验任务。其中,Errors会通过key映射到内部组件的errors。这个属性的keys应当与values中的相匹配。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读