烦恼和焦虑大都来源于无知。共勉!
记录一下setFieldsValue失败的血泪史,使用Antd的应该都会经常使用Form表单吧,编辑表单的时候经常需要回填默认值,这里有3个API可以使用,setFields, setFieldValue, setFieldsValue。
在线代码演示: stackblitz.com/edit/react-…
import React, { useEffect } from 'react';
import { Form, Input, Table, Button } from 'antd';
import { dataSource, detailResponse } from './formDemoData';
export default () => {
const [form] = Form.useForm();
const columns1 = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: 'value',
dataIndex: 'value',
key: 'value',
render: (text, record, index) => {
return (
<>
<Form.Item noStyle name={['b', index, 'value']}>
<Input />
</Form.Item>
</>
);
},
},
];
const columns2 = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: 'value',
dataIndex: 'value',
key: 'value',
render: (text, record, index) => {
return (
<>
<Form.Item noStyle name={['c', 'b', index, 'value']}>
<Input />
</Form.Item>
</>
);
},
},
];
const columns3 = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: 'value',
dataIndex: 'value',
key: 'value',
render: (text, record, index) => {
return (
<>
<Form.Item noStyle name={['c', 'c1', 'b', index, 'value']}>
<Input />
</Form.Item>
</>
);
},
},
];
useEffect(() => {
setTimeout(() => {
form.setFieldsValue(detailResponse);
// form.setFieldValue('a', detailResponse.a);
// form.setFieldValue('b', detailResponse.b);
// form.setFieldValue(['c', 'b'], detailResponse.c.b);
// form.setFieldValue(['c', 'c1', 'b'], detailResponse.c.c1.b);
// form.setFieldValue(['c', 'c1', 'c2'], detailResponse.c.c1.c2);
// form.setFields([
// { name: 'a', value: detailResponse.a},
// { name: 'b', value: detailResponse.b},
// { name: ['c', 'b'], value: detailResponse.c.b},
// { name: ['c', 'c1', 'b'], value: detailResponse.c.c1.b},
// { name: ['c', 'c1', 'c2'], value: detailResponse.c.c1.c2}
// ])
}, 1000);
}, []);
const onFinish = (values) => {
console.log(values);
};
return (
<div>
<h3>antd Form复杂表单</h3>
<Form form={form} onFinish={onFinish}>
<Form.Item label="一级字段a" name="a">
<Input />
</Form.Item>
<Form.Item label="一级字段是数组b" name="b">
<Table
columns={columns1}
dataSource={dataSource}
pagination={false}
/>
</Form.Item>
<Form.Item label="二级是数组【c.b】" name={['c', 'b']}>
<Table
columns={columns2}
dataSource={dataSource}
pagination={false}
/>
</Form.Item>
<Form.Item label="三级是数组【c.c1.b】" name={['c', 'c1', 'b']}>
<Table
columns={columns3}
dataSource={dataSource}
pagination={false}
/>
</Form.Item>
<Form.Item label="三级字段c.c1.c2" name={['c', 'c1', 'c2']}>
<Input />
</Form.Item>
<Button type="primary" htmlType="submit">
提交
</Button>
</Form>
</div>
);
};
// formDemoData.js
const bList = [
{ id: 1, value: 'b1' },
{ id: 2, value: 'b2' },
];
export const detailResponse = {
a: 'a',
b: bList,
c: {
b: bList,
c1: {
c2: 'c2',
b: bList,
},
},
};
export const dataSource = [
{
key: '1',
id: 1,
name: '胡彦斌',
age: 32,
},
{
key: '2',
id: 2,
name: '吴彦祖',
age: 32,
},
];
到这里大家应该发现了,嗯?这一切都很正常,为什么开头要说血泪史呢? 这是因为demo,demo就是demo,数据提交和返回值都是自己定义好的,不会有什么问题,但做项目的时候,字段名可能很长,笔者就是认为就是Form.setFilesValue能有什么问题,但默认值就是显示不出来,数据格式就是 data.a.b 是个数组,怎么就有问题了呢?
百度了好久,甚至在github上找到了issue,说setFieldsValue没有考虑namePath的情况 github.com/react-compo…
之前也没有发现setFieldsValue不支持嵌套啊,写了这么多年代码,着实给我整懵了!
一番折腾后,在晚上十点钟,终于找到了我想要的答案,原来是返回的字段名和提交的字段名不一致导致的,捶胸顿足啊!!!
之前也不是没发现提交和返回的字段不一致,只是没发现嵌套的二级字段也不一样,这样的话就需要小心了。
// 提交字段
const params = {
// ...
activityFinalAccountsDTO: {
// ...
branchOfficeFinalAccountsDTOList: [{}]
}
}
// 返回值字段
const response = {
// ...
activityFinalAccountsInfo: {
// ...
branchOfficeFinalAccountsInfos: [{}]
}
}
// bugfix: setFilesValue 前统一字段名
activityFinalAccountsInfo.branchOfficeFinalAccountsDTOList = activityFinalAccountsInfo.branchOfficeFinalAccountsInfos
form.setFieldsValue({
// ...
activityFinalAccountsDTO: activityFinalAccountsInfo
})
总结:复杂表单提交和有默认值的情况下,一定要注意前后字段名是否一致,尤其是有嵌套的字段名是否一致,不一致的时候,要在 setFilesValue 前统一字段名。