从 v1.x 迁移到 v2.x

重大变更

最低要求

  • 由于 Formik 2 基于 React Hooks 构建,因此您必须使用 React 16.8.x 或更高版本。
  • 由于 Formik 2 使用了 unknown 类型,因此如果您使用 TypeScript,则必须使用 TypeScript 3.0 或更高版本。

Formik 2.x 中有一些重大更改。幸运的是,这些更改可能不会影响很多人。

resetForm

在 Formik 2 中,我们引入了用于更多初始状态的新 props:initialErrorsinitialTouchedinitialStatus。因此,resetForm 的签名已更改。它不再可以选择仅接受表单的下一个初始值。它现在可以选择接受 Formik 的部分下一个初始状态。

v1

// Reset to `initialValues`
formik.resetForm();
// Reset form and set the next `initialValues` of the form
formik.resetForm({ name: '', email: '' });

v2

// Reset the form. This will set the next initial state of
// Formik to the `initialValues`, `initialErrors`, `initialTouched`,
// `initialStatus` props.
formik.resetForm();
// Reset the form back to `initialXXXX` but change next
// `initialValues` to a custom value
formik.resetForm({
values: { name: 'Custom initial values', email: '' },
});
// Reset form back to `initialXXXX`, but change next `initialValues`
// and `initialErrors` of the form
formik.resetForm({
values: { name: '', email: '' },
errors: { name: 'Something special' },
});
// Reset form back to `initialXXXX`, but change next `initialStatus` to 'Foo'
formik.resetForm({
status: 'Foo',
});

setError

此方法在 v1.x 版本中已弃用了一段时间,并带有警告。它在 v2 中已完全移除。请改用 Formik 的 setStatus(status)。它的工作方式相同。注意:这不是 setErrors(复数),setErrors 仍然存在。

validate

您可能知道,您可以从 validate 返回验证错误的 Promise。在 1.x 中,此 Promise 是否已解决或拒绝并不重要,因为在这两种情况下,Promise 的有效负载都被解释为验证错误。在 2.x 中,拒绝将被解释为实际异常,并且不会更新表单错误状态。任何返回已拒绝错误 Promise 的验证函数都需要调整为改为返回已解决的错误 Promise。

ref

目前,您无法使用 ref prop 将 ref 附加到 Formik。但是,您仍然可以使用 innerRef prop 来解决此问题。我们有一些正在进行中的工作 #2208 以改为使用 React.forwardRef

isValid

此属性不再考虑 dirty 的值。这意味着,如果您希望在表单未 dirty 时禁用提交按钮(即在第一次渲染时以及值未更改时),则必须显式检查它。

<button disabled={!isValid || !dirty} type="submit">
Submit
</button>

TypeScript 更改

FormikActions

FormikActions 已重命名为 FormikHelpers 导入或为该类型设置别名应该是一个简单的更改。

v1

import { FormikActions } from 'formik';

v2

import { FormikHelpers as FormikActions } from 'formik';

FieldProps

FieldProps 现在接受两个泛型类型参数。这两个参数都是可选的,但 FormValues 已从第一个参数移动到第二个参数。

v1

type Props = FieldProps<FormValues>;

v2

type Props = FieldProps<FieldValue, FormValues>;

新增功能?

复选框和多选

与 Angular、Vue 或 Svelte 类似,Formik 2 使用内置的数组绑定和布尔行为“修复”了 React 复选框和多选。这是 Formik 1.x 中最令人困惑的事情之一。

import React from 'react';
import { Formik, Field, Form } from 'formik';
import { Debug } from './Debug';
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const CheckboxExample = () => (
<div>
<h1>Checkboxes</h1>
<p>
This example demonstrates how to properly create checkboxes with Formik.
</p>
<Formik
initialValues={{
isAwesome: false,
terms: false,
newsletter: false,
jobType: ['designer'],
location: [],
}}
onSubmit={async values => {
await sleep(1000);
alert(JSON.stringify(values, null, 2));
}}
>
{({ isSubmitting, getFieldProps, handleChange, handleBlur, values }) => (
<Form>
{/*
This first checkbox will result in a boolean value being stored.
*/}
<div className="label">Basic Info</div>
<label>
<Field type="checkbox" name="isAwesome" />
Are you awesome?
</label>
{/*
Multiple checkboxes with the same name attribute, but different
value attributes will be considered a "checkbox group". Formik will automagically
bind the checked values to a single array for your benefit. All the add and remove
logic will be taken care of for you.
*/}
<div className="label">
What best describes you? (check all that apply)
</div>
<label>
<Field type="checkbox" name="jobType" value="designer" />
Designer
</label>
<label>
<Field type="checkbox" name="jobType" value="developer" />
Developer
</label>
<label>
<Field type="checkbox" name="jobType" value="product" />
Product Manager
</label>
{/*
You do not _need_ to use <Field>/useField to get this behavior,
using handleChange, handleBlur, and values works as well.
*/}
<label>
<input
type="checkbox"
name="jobType"
value="founder"
checked={values.jobType.includes('founder')}
onChange={handleChange}
onBlur={handleBlur}
/>
CEO / Founder
</label>
{/*
The <select> element will also behave the same way if
you pass `multiple` prop to it.
*/}
<label htmlFor="location">Where do you work?</label>
<Field
component="select"
id="location"
name="location"
multiple={true}
>
<option value="NY">New York</option>
<option value="SF">San Francisco</option>
<option value="CH">Chicago</option>
<option value="OTHER">Other</option>
</Field>
<label>
<Field type="checkbox" name="terms" />I accept the terms and
conditions.
</label>
{/* Here's how you can use a checkbox to show / hide another field */}
{!!values.terms ? (
<div>
<label>
<Field type="checkbox" name="newsletter" />
Send me the newsletter <em style={{ color: 'rebeccapurple' }}>
(This is only shown if terms = true)
</em>
</label>
</div>
) : null}
<button type="submit" disabled={isSubmitting}>
Submit
</button>
<Debug />
</Form>
)}
</Formik>
</div>
);
export default CheckboxExample;

useField()

正如您所想,它就像 <Field>,但使用的是 Hook。请参阅文档了解用法。

useFormikContext()

一个等效于 connect() 的 Hook。

<Field as>

<Field/> 现在接受一个名为 as 的 prop,它会将 onChangeonBlurvalue 等直接注入到组件或字符串中。这对于使用 Emotion 或 Styled 组件的人很有用,因为他们不再需要在包装函数中清理 component 的 render props。

// <input className="form-input" placeholder="Jane" />
<Field name="firstName" className="form-input" placeholder="Jane" />
// <textarea className="form-textarea"/></textarea>
<Field name="message" as="textarea" className="form-textarea"/>
// <select className="my-select"/>
<Field name="colors" as="select" className="my-select">
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</Field>
// with styled-components/emotion
const MyStyledInput = styled.input`
padding: .5em;
border: 1px solid #eee;
/* ... */
`
const MyStyledTextarea = MyStyledInput.withComponent('textarea');
// <input className="czx_123" placeholder="google.com" />
<Field name="website" as={MyStyledInput} placeholder="google.com"/>
// <textarea placeholder="Post a message..." rows={5}></textarea>
<Field name="message" as={MyStyledTextArea} placeholder="Post a message.." rows={4}/>

getFieldProps(nameOrProps)

FormikProps 有两个有用的新增功能,getFieldPropsgetFieldMeta。如果您喜欢 prop 传递、使用基于上下文的 API 或正在构建自定义 useField,则这些 prop 获取器可能很有用。

export interface FieldInputProps<Value> {
/** Value of the field */
value: Value;
/** Name of the field */
name: string;
/** Multiple select? */
multiple?: boolean;
/** Is the field checked? */
checked?: boolean;
/** Change event handler */
onChange: FormikHandlers['handleChange'];
/** Blur event handler */
onBlur: FormikHandlers['handleBlur'];
}

getFieldMeta(name)

给定一个名称,它将返回一个对象。

export interface FieldMetaProps<Value> {
/** Value of the field */
value: Value;
/** Error message of the field */
error?: string;
/** Has the field been visited? */
touched: boolean;
/** Initial value of the field */
initialValue?: Value;
/** Initial touched state of the field */
initialTouched: boolean;
/** Initial error message of the field */
initialError?: string;
}

其他

  • 现在导出了 FormikContext
  • validateOnMount?: boolean = false
  • 已添加 initialErrorsinitialTouchedinitialStatus

弃用警告

所有 render props 都已弃用,并带有控制台警告。

对于 <Field><FastField><Formik><FieldArray>render prop 已弃用并带有警告,因为它将在以后的版本中移除。请改用子回调函数。此弃用旨在与 React Context Consumer 的用法保持一致。

- <Field name="firstName" render={props => ....} />
+ <Field name="firstName">{props => ... }</Field>
此页面是否有帮助?

订阅我们的时事通讯

最新的 Formik 新闻、文章和资源,发送到您的收件箱。

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