<FastField />

開始之前

<FastField /> 主要用於效能*優化*。然而,在真正需要之前,您並不需要使用它。只有在您熟悉 React 的 shouldComponentUpdate() 的運作方式後,才繼續閱讀。我們已經警告過您了。

不開玩笑。在繼續之前,請先查看 React 官方文件中以下部分

概述

<FastField /><Field /> 的優化版本,適用於大型表單(約 30 個以上欄位)或欄位具有非常昂貴的驗證需求時。<FastField /><Field> 具有完全相同的 API,但在內部實作了 shouldComponentUpdate(),以阻止所有額外的重新渲染,除非 Formik 狀態中與 <FastField /> 相關的部分/片段有直接更新。

例如,<FastField name="firstName" /> 只會在以下情況下重新渲染:

  • values.firstNameerrors.firstNametouched.firstNameisSubmitting 發生變更。這是透過淺層比較來判斷的。注意:支援點路徑。
  • <FastField name="firstName" /> 中新增/移除屬性
  • name 屬性變更

除了上述情況之外,當 Formik 狀態的其他部分發生變更時,<FastField /> 不會重新渲染。然而,由 <FastField /> 觸發的所有更新都會觸發其他「一般」<Field /> 元件的重新渲染。

何時使用 <FastField />

如果表單中的 <Field /> 與所有其他 <Field />「獨立」,則可以使用 <FastField />.

更具體地說,如果 <Field /> 的行為或渲染內容不基於其他 <Field /><FastField /> 的 Formik 狀態片段的更新,並且它不依賴於頂層 <Formik /> 狀態的其他部分(例如 isValidatingsubmitCount),則可以使用 <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>
<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 新聞、文章和資源,將會寄送到您的收件匣。

版權所有 © 2020 Formium, Inc. 保留所有權利。