<FastField />
主要用於效能*優化*。然而,在真正需要之前,您並不需要使用它。只有在您熟悉 React 的 shouldComponentUpdate()
的運作方式後,才繼續閱讀。我們已經警告過您了。
不開玩笑。在繼續之前,請先查看 React 官方文件中以下部分
<FastField />
是 <Field />
的優化版本,適用於大型表單(約 30 個以上欄位)或欄位具有非常昂貴的驗證需求時。<FastField />
與 <Field>
具有完全相同的 API,但在內部實作了 shouldComponentUpdate()
,以阻止所有額外的重新渲染,除非 Formik 狀態中與 <FastField />
相關的部分/片段有直接更新。
例如,<FastField name="firstName" />
只會在以下情況下重新渲染:
values.firstName
、errors.firstName
、touched.firstName
或 isSubmitting
發生變更。這是透過淺層比較來判斷的。注意:支援點路徑。<FastField name="firstName" />
中新增/移除屬性name
屬性變更除了上述情況之外,當 Formik 狀態的其他部分發生變更時,<FastField />
不會重新渲染。然而,由 <FastField />
觸發的所有更新都會觸發其他「一般」<Field />
元件的重新渲染。
<FastField />
如果表單中的 <Field />
與所有其他 <Field />
「獨立」,則可以使用 <FastField />
.
更具體地說,如果 <Field />
的行為或渲染內容不基於其他 <Field />
或 <FastField />
的 Formik 狀態片段的更新,並且它不依賴於頂層 <Formik />
狀態的其他部分(例如 isValidating
、submitCount
),則可以使用 <FastField />
作為 <Field />
的直接替代品。
import React from 'react';import { Formik, Field, FastField, Form } from 'formik';import * as Yup from 'yup';const Basic = () => (<div><h1>Sign Up</h1><FormikinitialValues={{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 tovalues.firstName, touched.firstName, errors.firstName */}<label htmlFor="firstName">First Name</label><FastField name="firstName" placeholder="Weezy" />{/** Updates for all changes because it's from thetop-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 fromfrom 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 */}<buttontype="button"onClick={form.setFieldValue('middleInitial', 'J')}>J</button></div>)}</FastField>{/** Updates for all changes to Formik stateand 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 insideof 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 andall 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>);