ant-design/components/form/v3.en-US.md
偏右 a0eb9d31de
chore: merge master into feature (#28751)
* fix: Transfer dataSource cannot be immutable (#28675)

close #28662

* docs: fix errors in example code (#28677)

* ci: expand ie check (#28673)

* ci: expand ie check

* Update issue-open-check.yml

* perf(📦): reduce @babel/runtime package size (#28678)

* perf(📦): reduce @babel/runtime package size

04cd73dea1

* chore(🆙): upgrade @ant-design/react-slick to esm support version

* upgrade @ant-design/tools

* ci: add open condition (#28682)

* fix(Slider): forcePopupAlign null when unmounted (#28699)

* docs: Update overview.zh-CN.md (#28703)

* docs: Update resources.en-US.md (#28701)

* chore: bump rc-select to 12.1.0 (#28715)

* fix: stylelint plugin (#28730)

* Update package.json

* perf(📦): upgrade rc-image to 5.x (#28727)

* refactor: upgrade rc-image to 5.x

reduce bundle size

* upgrade rc-image

* upgrade @ant-design/tools

https://github.com/ant-design/antd-tools/pull/226

* rc-image 5.0.0

* fix image preview icon missing

* refactor code

* docs: example of synchronous rc-tree (#28648)

* ci: fix outputs type

过程中的使用 string。奇怪啊,之前测试过的,今天点的时候发现不行了

* Update package.json

* fix: site overflow cause sticky invalid (#28741)

* fix: site overflow cause sticky invalid

* disable auto scroll

* chore: upgrade rc-dialog and rc-drawer (#28749)

* chore: upgrade rc-dialog and rc-drawer (#28687)

* chore: upgrade rc-dialog and rc-drawer

* upgrade rc-util

* update snapshots

* upgrade rc-util

* upgrade rc-util

* update snapshots

* upgrade rc-dialog

* perf: remove duplicated rc-dialog

Co-authored-by: 骗你是小猫咪 <darryshaw@gmail.com>

Co-authored-by: bigbigbo <zxb141242@163.com>
Co-authored-by: xrkffgg <xrkffgg@gmail.com>
Co-authored-by: Yann Pringault <yann.pringault@gmail.com>
Co-authored-by: godfather <greenday.wj@foxmail.com>
Co-authored-by: Mateusz Wierzbicki <22788841+mateusz-wierzbicki@users.noreply.github.com>
Co-authored-by: Kermit <kermitlx@outlook.com>
Co-authored-by: AkiJoey <akijoey1010635951@gmail.com>
Co-authored-by: qqabcv520 <605655316@qq.com>
Co-authored-by: 骗你是小猫咪 <darryshaw@gmail.com>
2021-01-08 10:14:01 +08:00

327 lines
6.8 KiB
Markdown

---
title: Migrate Form to v4
skip: true
---
### Remove Form.create
Form of v4 does not need to create context by calling `Form.create()`. Form now has it's own data scope and you don't need `getFieldDecorator` anymore. Just use Form.Item directly:
```jsx
// antd v3
const Demo = ({ form: { getFieldDecorator } }) => (
<Form>
<Form.Item>
{getFieldDecorator('username', {
rules: [{ required: true }],
})(<Input />)}
</Form.Item>
</Form>
);
const WrappedDemo = Form.create()(Demo);
```
To:
```jsx
// antd v4
const Demo = () => (
<Form>
<Form.Item name="username" rules={[{ required: true }]}>
<Input />
</Form.Item>
</Form>
);
```
Since `Form.create()` is removed, methods like `onFieldsChange` have moved to `Form` and form state is controlled by a `fields` prop. ref [example](/components/form/#components-form-demo-global-state)。
### Form control
If you want to control form, you can use `Form.useForm()` to create Form instance for operation:
```jsx
// antd v3
const Demo = ({ form: { setFieldsValue } }) => {
React.useEffect(() => {
setFieldsValue({
username: 'Bamboo',
});
}, []);
return (
<Form>
<Form.Item>
{getFieldDecorator('username', {
rules: [{ required: true }],
})(<Input />)}
</Form.Item>
</Form>
);
};
const WrappedDemo = Form.create()(Demo);
```
To:
```jsx
// antd v4
const Demo = () => {
const [form] = Form.useForm();
React.useEffect(() => {
form.setFieldsValue({
username: 'Bamboo',
});
}, []);
return (
<Form form={form}>
<Form.Item name="username" rules={[{ required: true }]}>
<Input />
</Form.Item>
</Form>
);
};
```
For class component, you can use `ref` to access instance:
```jsx
// antd v4
class Demo extends React.Component {
formRef = React.createRef();
componentDidMount() {
this.formRef.current.setFieldsValue({
username: 'Bamboo',
});
}
render() {
return (
<Form ref={this.formRef}>
<Form.Item name="username" rules={[{ required: true }]}>
<Input />
</Form.Item>
</Form>
);
}
}
```
If you don't want to use the Item style, you can use `noStyle` prop to remove it:
```jsx
// antd v3
const Demo = ({ form: { getFieldDecorator } }) => {
return <Form>{getFieldDecorator('username')(<Input />)}</Form>;
};
const WrappedDemo = Form.create()(Demo);
```
To:
```jsx
// antd v4
const Demo = () => {
return (
<Form>
<Form.Item name="username" noStyle>
<Input />
</Form.Item>
</Form>
);
};
```
### Linkage with field
New Form uses incremental update which only updates related field. So if there is some linkage between fields or updates with the whole form, you can use [`dependencies`](/components/form/#dependencies) or [`shouldUpdate`](/components/form/#shouldUpdate) to handle that.
### replace onSubmit with onFinish
You need to listen to `onSubmit` and call `validateFields` to handle validation in old Form. New Form provides `onFinish` which will only trigger when validation has passed:
```jsx
// antd v3
const Demo = ({ form: { getFieldDecorator, validateFields } }) => {
const onSubmit = e => {
e.preventDefault();
validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
};
return (
<Form onSubmit={onSubmit}>
<Form.Item>
{getFieldDecorator('username', {
rules: [{ required: true }],
})(<Input />)}
</Form.Item>
</Form>
);
};
const WrappedDemo = Form.create()(Demo);
```
To:
```jsx
// antd v4
const Demo = () => {
const onFinish = values => {
console.log('Received values of form: ', values);
};
return (
<Form onFinish={onFinish}>
<Form.Item name="username" rules={[{ required: true }]}>
<Input />
</Form.Item>
</Form>
);
};
```
## Replace validateFieldsAndScroll with scrollToField
New version recommend use `onFinish` for submit after validation. Thus `validateFieldsAndScroll` is changed to more flexible method `scrollToField`:
```jsx
// antd v3
onSubmit = () => {
form.validateFieldsAndScroll((error, values) => {
// Your logic
});
};
```
To:
```jsx
// antd v4
onFinishFailed = ({ errorFields }) => {
form.scrollToField(errorFields[0].name);
};
```
### Initialization
Besides, we move `initialValue` into Form to avoid field with same name both using `initialValue` to cause conflict:
```jsx
// antd v3
const Demo = ({ form: { getFieldDecorator } }) => (
<Form>
<Form.Item>
{getFieldDecorator('username', {
rules: [{ required: true }],
initialValue: 'Bamboo',
})(<Input />)}
</Form.Item>
</Form>
);
const WrappedDemo = Form.create()(Demo);
```
To:
```jsx
// antd v4
const Demo = () => (
<Form initialValues={{ username: 'Bamboo' }}>
<Form.Item name="username" rules={[{ required: true }]}>
<Input />
</Form.Item>
</Form>
);
```
In v3, modifying the `initialValue` of un-operated field will update the field value synchronously, which is a bug. However, since it has been used as a feature for a long time, we have not fixed it. In v4, the bug has been fixed. `initialValues` only takes effect when initializing and resetting the form.
### Nested field paths using arrays
In the past versions we used `.` to represent nested paths (such as `user.name` to represent `{ user: { name: '' } }`). However, in some backend systems, `.` is also included in the variable name. This causes the user to need additional code to convert, so in the new version, nested paths are represented by arrays to avoid unexpected behavior (eg `['user', 'name']`).
Therefore, paths returned by methods such as `getFieldsError` are always in an array form for the user to handle:
```jsx
form.getFieldsError();
/*
[
{ name: ['user', 'name'], errors: [] },
{ name: ['user', 'age'], errors: ['Some error message'] },
]
*/
```
Nested field definition has changed from:
```jsx
// antd v3
<Form.Item label="Firstname">{getFieldDecorator('user.0.firstname', {})(<Input />)}</Form.Item>
```
To
```jsx
// antd v4
<Form.Item name={['user', 0, 'firstname']} label="Firstname">
<Input />
</Form.Item>
```
Similarly using `setFieldsValue` has changed from:
```jsx
// antd v3
this.formRef.current.setFieldsValue({
'user.0.firstname': 'John',
});
```
To
```jsx
// antd v4
this.formRef.current.setFieldsValue({
user: [
{
firstname: 'John',
},
],
});
```
### Remove callback in validateFields
`validateFields` will return a Promise, so you can handle the error with `async/await` or `then/catch`. It is no longer necessary to determine if `errors` is empty:
```jsx
// antd v3
validateFields((err, value) => {
if (!err) {
// Do something with value
}
});
```
To
```jsx
// antd v4
validateFields().then(values => {
// Do something with value
});
```