<FastField />

在我们开始之前

¥Before we start

<FastField /> 用于性能优化。然而,在你真正使用它之前,你并不需要使用它。仅当你熟悉 React 的 shouldComponentUpdate() 工作原理时才可以继续。你被警告了。

¥<FastField /> is meant for performance optimization. However, you really do not need to use it until you do. Only proceed if you are familiar with how React's shouldComponentUpdate() works. You have been warned.

不。严重地。在继续之前,请查看官方 React 文档的以下部分

¥No. Seriously. Please review the following parts of the official React documentation before continuing

概述

¥Overview

<FastField /><Field /> 的优化版本,旨在用于大型表单(~30+ 字段)或当字段具有非常昂贵的验证要求时。<FastField /> 具有与 <Field> 完全相同的 API,但在内部实现 shouldComponentUpdate() 以阻止所有其他重新渲染,除非直接更新 <FastField /> 的相关部分/Formik 状态切片。

¥<FastField /> is an optimized version of <Field /> meant to be used on large forms (~30+ fields) or when a field has very expensive validation requirements. <FastField /> has the same exact API as <Field>, but implements shouldComponentUpdate() internally to block all additional re-renders unless there are direct updates to the <FastField />'s relevant parts/slice of Formik state.

例如,<FastField name="firstName" /> 仅在存在以下情况时才会重新渲染:

¥For example, <FastField name="firstName" /> will only re-render when there are:

  • 更改为 values.firstNameerrors.firstNametouched.firstNameisSubmitting。这是通过浅层比较而确定的。注意:支持点路径。

    ¥Changes to values.firstName, errors.firstName, touched.firstName, or isSubmitting. This is determined by shallow comparison. Note: dotpaths are supported.

  • <FastField name="firstName" /> 上添加/删除了一个属性

    ¥A prop is added/removed to the <FastField name="firstName" />

  • name 属性发生变化

    ¥The name prop changes

除了上述情况外,当 Formik 的其他部分状态发生变化时,<FastField /> 不会重新渲染。但是,由 <FastField /> 触发的所有更新都会触发对其他 "vanilla" <Field /> 组件的重新渲染。

¥Other than for these aforementioned situations, <FastField /> will not re-render when other parts of Formik state change. However, all updates triggered by a <FastField /> will trigger re-renders to other "vanilla" <Field /> components.

何时使用 <FastField />

¥When to use <FastField />

如果 <Field /> 是表单中所有其他 <Field /> 的 "independent",那么你可以使用 <FastField />

¥If a <Field /> is "independent" of all other <Field />'s in your form, then you can use <FastField />.

更具体地说,如果 <Field /> 不改变行为或渲染任何基于对另一个 <Field /><FastField /> 的 Formik 状态切片的更新的内容,并且它不依赖于顶层 <Formik /> 状态的其他部分(例如 isValidatingsubmitCount),那么你 可以使用 <FastField /> 作为 <Field /> 的直接替代品。

¥More specifically, if the <Field /> does not change behavior or render anything that is based on updates to another <Field /> or <FastField />'s slice of Formik state AND it does not rely on other parts of top-level <Formik /> state (e.g. isValidating, submitCount), then you can use <FastField /> as a drop-in replacement to <Field />.

示例

¥Example

import React from 'react';
import { Formik, Field, FastField, Form } from 'formik';
import * as Yup from 'yup';
const Basic = () => (
<div>
<h1>Sign Up</h1>
<Formik
initialValues={{
firstName: '',
lastName: '',
email: '',
}}
validationSchema={Yup.object().shape({
firstName: Yup.string().required(),
middleInitial: Yup.string(),
lastName: Yup.string().required(),
email: Yup.string().email().required(),
})}
onSubmit={values => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
}, 500);
}}
>
{formikProps => (
<Form>
{/** This <FastField> only updates for changes made to
values.firstName, touched.firstName, errors.firstName */}
<label htmlFor="firstName">First Name</label>
<FastField name="firstName" placeholder="Weezy" />
{/** Updates for all changes because it's from the
top-level formikProps which get all updates */}
{formikProps.touched.firstName && formikProps.errors.firstName && (
<div>{formikProps.errors.firstName}</div>
)}
<label htmlFor="middleInitial">Middle Initial</label>
<FastField name="middleInitial" placeholder="F">
{({ field, form, meta }) => (
<div>
<input {...field} />
{/**
* This updates normally because it's from the same slice of Formik state,
* i.e. path to the object matches the name of this <FastField />
*/}
{meta.touched ? meta.error : null}
{/** This won't ever update since it's coming from
from another <Field>/<FastField>'s (i.e. firstName's) slice */}
{form.touched.firstName && form.errors.firstName
? form.errors.firstName
: null}
{/* This doesn't update either */}
{form.submitCount}
{/* Imperative methods still work as expected */}
<button
type="button"
onClick={form.setFieldValue('middleInitial', 'J')}
>
J
</button>
</div>
)}
</FastField>
{/** Updates for all changes to Formik state
and all changes by all <Field>s and <FastField>s */}
<label htmlFor="lastName">LastName</label>
<Field name="lastName" placeholder="Baby">
{({ field, form, meta }) => (
<div>
<input {...field} />
{/** Works because this is inside
of a <Field/>, which gets all updates */}
{form.touched.firstName && form.errors.firstName
? form.errors.firstName
: null}
</div>
)}
</Field>
{/** Updates for all changes to Formik state and
all changes by all <Field>s and <FastField>s */}
<label htmlFor="email">Email</label>
<Field name="email" placeholder="jane@acme.com" type="email" />
<button type="submit">Submit</button>
</Form>
)}
</Formik>
</div>
);
Formik 中文网 - 粤ICP备13048890号