1、問題描述
在使用Antd組件Form表單的過程中,會出現FormItem同名的情況,此時要特別注意同名引起的表單行為異常問題,主要表現在以下方面:
(1)同名表單項的值共享,並且其中一個的值改變,另外的同名表單的值也一致改變。
(2)同名表單中,表單控件比如<Input />的onChange等事件會出現行為異常的情況。
源碼如下圖所示:
import React, { PureComponent } from 'react';
import { Form, Input } from 'antd';
import styles from './styles.less';
@Form.create()
class Example extends PureComponent {
render() {
return (
<div className={styles.example}>
{
data.map((item, index) => (
<Form key={index}>
<h2>表單{index + 1}</h2>
<div>
<Form.Item label="名稱">
{this.props.form.getFieldDecorator('name')(
<Input />
)}
</Form.Item>
</div>
<div>
<Form.Item label="數值">
{this.props.form.getFieldDecorator('value')(
<Input onChange={() => { console.log('index:', index); }} />
)}
</Form.Item>
</div>
</Form>
))
}
</div>
);
}
}
const data = [{
name: '名稱1',
value: 1,
}, {
name: '名稱2',
value: 2,
}];
export default Example;
渲染界面如下圖:

此時如果通過在表單1和表單2中輸入數值觸發兩者的onChange事件,會發現控制台輸出都是 index:1;
連表單項的<h2>表單{index + 1}</h2>內容都能正常渲染表單1、表單2,為什么onChange始終輸出1呢?正常應該輸出 index:0 和 index:1 。
2、問題分析:
同名的表單被當成完全相同的表單項處理,數值和onChange行為都一樣,所以兩個表單項的onChange始終只執行了最后一個表單項的onChange事件,index始終輸出1.
要想得到正確的結果,應該分別分別修改兩個表單中的域名,可以在現有字段名的基礎上加上index,即改為如下內容:
<div>
<Form.Item label="名稱">
{this.props.form.getFieldDecorator('name' + index)(
<Input />
)}
</Form.Item>
</div>
<div>
<Form.Item label="數值">
{this.props.form.getFieldDecorator('value' + index)(
<Input onChange={() => { console.log('index:', index); }} />
)}
</Form.Item>
</div>
此時渲染的表單1和表單2的數值項的字段名分別是vlaue0和value1,就不會相互影響,經測試能正常輸出index:0和index:1. 表單行為不再混淆。
3、拓展反思:
以上討論的FormItem名稱相同問題看似是個小問題,實際上很多情況如果不注意FormItem的名稱唯一性,會造成很多問題,比如同名Item的值相互影響,以及以上所說的onChange行為異常(容易出錯)。如果出現map渲染出多個表單時,可以利用名稱+索引值使表單項名稱唯一。
如有問題歡迎留言討論。
原創博客禁止抄襲,轉載請注明出處:原文地址:https://www.cnblogs.com/xiao-pengyou/
