从 v1.x 迁移到 v2.x

重大变化

¥Breaking Changes

最低要求

¥Minimum Requirements

  • 由于 Formik 2 是基于 React Hooks 构建的,因此你必须使用 React 16.8.x 或更高版本

    ¥Since Formik 2 is built on top of React Hooks, you must be on React 16.8.x or higher

  • 由于 Formik 2 使用 unknown 类型,因此你必须使用 TypeScript 3.0 或更高版本(如果你使用 TypeScript)

    ¥Since Formik 2 uses the unknown type, you must be on TypeScript 3.0 or higher (if you use TypeScript)

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

¥There are a few breaking changes in Formik 2.x. Luckily, these probably won't impact many people:

resetForm

在 Formik 2 中,我们引入了新的 props 以实现更多初始状态:initialErrors, initialTouched, initialStatus.因此,resetForm 的签名发生了变化。而不是选择性地只接受表单的下一个初始值。现在它可以选择接受 Formik 的部分下一个初始状态。

¥With Formik 2, we introduced the new props for more initial state: initialErrors, initialTouched, initialStatus. Therefore, resetForm's signature has changed. Instead of optionally accepting just the next initial values of the form. It now optionally accepts the partial next initial state of 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(复数),它仍然存在。

¥This method has been deprecated for a while with a warning in v1.x releases. It's fully removed in v2. Please use Formik's setStatus(status) instead. It works identically. Note: this is/was not setErrors (plural) which is still around.

validate

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

¥As you may know, you can return a Promise of a validation error from validate. In 1.x, it didn't matter if this promise is resolved or rejected as in both cases the payload of the promise was interpreted as the validation error. In 2.x, rejection will be interpreted as an actual exception and it won't update the form error state. Any validation function that returns a rejected promise of errors needs to be adjusted to return a resolved promise of errors instead.

ref

目前,你无法使用 ref 属性将引用附加到 Formik。但是,你仍然可以使用 innerRef 属性来解决此问题。我们有一些 WIP #2208 来代替使用 React.forwardRef

¥Currently, you can't attach a ref to Formik using the ref prop. However, you still can get around this issue using the prop innerRef. We have some WIP #2208 to instead use React.forwardRef.

isValid

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

¥This property does not take the value of dirty into account anymore. This means that if you want to disable a submit button when the form is not dirty (i.e. on first render and when values are unchanged), you have to explicitly check for it.

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

TypeScript 更改

¥Typescript changes

FormikActions

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

¥FormikActions has been renamed to FormikHelpers It should be a straightforward change to import or alias the type

v1

import { FormikActions } from 'formik';

v2

import { FormikHelpers as FormikActions } from 'formik';

FieldProps

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

¥FieldProps now accepts two generic type parameters. Both parameters are optional, but FormValues has been moved from the first to the second parameter.

v1

type Props = FieldProps<FormValues>;

v2

type Props = FieldProps<FieldValue, FormValues>;

什么是新的?

¥What's New?

复选框并选择多个

¥Checkboxes and Select multiple

与 Angular、Vue 或 Svelte 类似,Formik 2 "fixes" React 复选框和多选具有内置数组绑定和布尔行为。对于 Formik 1.x 中的人们来说,这是最令人困惑的事情之一。

¥Similarly to Angular, Vue, or Svelte, Formik 2 "fixes" React checkboxes and multi-selects with built-in array binding and boolean behavior. This was one of the most confusing things for people in 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>,但带有一个钩子。使用方法请参阅文档。

¥Just what you think, it's like <Field>, but with a hook. See docs for usage.

useFormikContext()

相当于 connect() 的钩子。

¥A hook that is equivalent to connect().

<Field as>

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

¥<Field/> now accepts a prop called as which will inject onChange, onBlur, value etc. directly through to the component or string. This is useful for folks using Emotion or Styled components as they no longer need to clean up component's render props in a wrapped function.

// <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)

FormikPropsgetFieldPropsgetFieldMeta 中有两个有用的补充。他们是肯特·C.如果你喜欢属性钻探,不使用基于上下文的 API,或者如果你正在构建自定义 useField.Dodds 式属性获取器,那么它可能会很有用。

¥There are two useful additions to FormikProps, getFieldProps and getFieldMeta. These are Kent C. Dodds-esque prop getters that can be useful if you love prop drilling, are not using the context-based API's, or if you are building a custom useField.

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)

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

¥Given a name it will return an object:

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;
}

杂项

¥Misc

  • FormikContext 现已导出

    ¥FormikContext is now exported

  • validateOnMount?: boolean = false

  • 已添加 initialErrorsinitialTouchedinitialStatus

    ¥initialErrors, initialTouched, initialStatus have been added

弃用警告

¥Deprecation Warnings

所有 render 属性均已弃用,并带有控制台警告。

¥All render props have been deprecated with a console warning.

对于 <Field><FastField><Formik><FieldArray>render 属性已被弃用并带有警告,因为它将在未来版本中删除。相反,请使用子回调函数。此弃用旨在与 React Context Consumer 的使用并行。

¥For <Field>, <FastField>, <Formik>,<FieldArray>, the render prop has been deprecated with a warning as it will be removed in future versions. Instead, use a child callback function. This deprecation is meant to parallel React Context Consumer's usage.

- <Field name="firstName" render={props => ....} />
+ <Field name="firstName">{props => ... }</Field>
Formik 中文网 - 粤ICP备13048890号