antd从v3升级到v4
# Form适配
# 1. 删除compatible兼容包
移除兼容包
import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css';
2
将Form放入其他antd引入中。
import { Form, Select, message, Button } from 'antd';
# 2. 删除create方法
移除
export default Form.create({})(SetDetainParking);
将export default
添加类或函数前面
export default class SetDetainParking extends Component {}
# 3. onSubmit替换为onFinish
在Form中的onSubmit修改为onFinish,并将自定义的onFinish方法修改为入参values并直接使用。
# 4. Item删除getFieldDecorator
将getFieldDecorator的参数都放入Form.Item中,修改":"为"="连接并添加"{}"。
# 5. 移除props.form
因为form已经从props中移除,所以需要使用form那么采用其他方式。
- class类型,则在class中添加一个
formRef = React.createRef();
属性,并在Form中绑定<Form ref={this.formRef}>
。 - 函数类型,则在函数中添加一个
const [form] = Form.useForm();
变量,并在Form中绑定<Form form={form}>
。
# 6. 设置初始值
除了直接中Form中通过initialValues的方式来设置初始化外,通过setFieldsValue也可以设置。
(1)class类型, 通过formRef = React.createRef();
获取form实例设置。
componentDidMount() {
this.formRef.current.setFieldsValue({
remark: this.props.data.remark
});
}
2
3
4
5
(2)函数类型,通过const [form] = Form.useForm();
获取form实例设置。
useEffect(() = ()=> {
cityGetOption({ cityId }).then(res => {
if (res.status) return;
const {
faceidOption: { open }
} = res.data;
form.setFieldsValue({
faceidOption: { open: open || false }
});
});
}, [cityId]);
2
3
4
5
6
7
8
9
10
11
12
# 7. Item包含两个组件
当Item中包含了InputNumber和span等其他的时候,那么无法通过name来访问到InputNumber,所以必须将InputNumber用Item包含。即Item包含一个Item和span。
# 8. CheckBox和Switch设置value
使用CheckBox的时候,需要在Item中设置valuePropName="checked
,不然无法设置正确的value。
# 9. callback替换
callback需要替换为 return Promise.reject
和return Promise.resolve()
。
# 10. 获取value来更新另一个value
当在render中使用一个value来更新另一个value时,那么不能再使用之前的this.props.form.getFieldValue
, 而需用通过onValuesChange={onValuesChange}
监听所有值的变化,更新state来实现更新另一个value。
const onValuesChange = (changedValues, allValues) => {
const operateType = allValues.operateType;
const costTimeType = typeof operateType === 'undefined' ? 0 : operateType * 1;
this.setState({
costTimeType
})
}
2
3
4
5
6
7
# 示范(v3/v4)
async getRefData() {
const {
form: { validateFieldsAndScroll },
dispatch,
selectedRow,
onCancel,
viewType,
} = this.props;
return new Promise((resolve, reject) => {
validateFieldsAndScroll((err, values) => {
if (err) return reject();
if (viewType === 'view') {
onCancel();
return resolve(values);
}
dispatch({
type: viewType === 'add' ? `${moduleName}/addOne` : `${moduleName}/modOne`,
payload: {
...selectedRow,
...values,
createDate: formatDate(values.createDate),
},
}).then(res => {
const { isSuccess } = res;
if (isSuccess) {
onCancel();
resolve(res);
}
});
});
});
}
<CommonModal modalOpts={modalProps}>
<Form {...this.formItemLayout}>
<Row>
<Col span={24}>
<Form.Item label={formatMessage({id: `${moduleName}.title`,defaultMessage: '标题',})} >
{getFieldDecorator('title', {
rules: [
{
required: true,
message: getPlaceholder(),
},
],
})(<Input disabled={disabled} placeholder={getPlaceholder()} />)}
</Form.Item>
</Col>
<Col span={24}>
<Form.Item label={formatMessage({id: `${moduleName}.statusCd`,defaultMessage: '状态',})}>
{getFieldDecorator('statusCd', {
rules: [
{
required: true,
message: getPlaceholder('', 'select'),
},
],
})(
<Select
allowClear
disabled={disabled}
style={{ width: '100%' }}
placeholder={getPlaceholder('', 'select')}
>
{STATUS_CD.map(item => {
return (
<Select.Option key={item.value} value={item.value}>
{item.label}
</Select.Option>
);
})}
</Select>
)}
</Form.Item>
</Col>
</Row>
</Form>
</CommonModal>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import { Form, Input, InputNumber, Button, Drawer } from 'antd';
import React from 'react';
const layout = {
labelCol: { span: 4 },
wrapperCol: { span: 18 },
};
const validateMessages = {
required: '${label} is required!',
types: {
email: '${label} is not a valid email!',
number: '${label} is not a valid number!',
},
number: {
range: '${label} must be between ${min} and ${max}',
},
};
// export const Index = (props) => {
const Index = (props) => {
const [form] = Form.useForm();
const handleOk = (e) => {
// console.log(form.getFieldsValue());
// form.getFieldsValue();
return form
.validateFields()
.then((values) => {
console.log('---values--', values);
})
.catch((error) => {
console.log('---error--', error);
});
};
const { visible, onCancel, onOk } = props;
return (
<Drawer
title="选择表单数据"
getContainer={false}
width={720}
onClose={onCancel}
visible={visible}
bodyStyle={{ paddingBottom: 80 }}
footer={
<div
style={{
textAlign: 'right',
}}
>
<Button onClick={onCancel} style={{ marginRight: 8 }}>
Cancel
</Button>
<Button onClick={handleOk} type="primary">
Submit
</Button>
</div>
}
>
<Form
{...layout}
name="nest-messages"
// onFinish={this.onFinish}
form={form}
validateMessages={validateMessages}
scrollToFirstError
initialValues={{
name: 'samy',
email: '123@qq.com',
}}
// onFinish={onFinish}
// onFinishFailed={onFinishFailed}
>
<Form.Item
name={['user', 'name']}
label="Name"
rules={[{ required: true }]}
>
<Input />
</Form.Item>
<Form.Item
name={['user', 'email']}
label="Email"
rules={[{ type: 'email' }]}
>
<Input />
</Form.Item>
<Form.Item
name={['user', 'age']}
label="Age"
rules={[{ type: 'number', min: 0, max: 99 }]}
>
<InputNumber />
</Form.Item>
<Form.Item name={['user', 'website']} label="Website">
<Input />
</Form.Item>
<Form.Item name={['user', 'introduction']} label="Introduction">
<Input.TextArea />
</Form.Item>
{/* <Form.Item wrapperCol={{ ...layout.wrapperCol, offset: 8 }}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item> */}
</Form>
</Drawer>
);
};
export default Index;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# 参考链接
https://ant.design/docs/react/migration-v4-cn