如何实现映射子组件的表单?解决字段同步变更问题
问题解决:Antd Form映射生成的子组件字段同步变更
问题场景
父组件包含根<Form>,子组件内有需要校验的输入字段,子组件通过数据映射循环生成。但修改其中任意一个子组件的字段时,所有子组件的对应字段都会同步变更,尝试给映射组件添加id无效。
原代码
父组件代码
<Form id="myForm" name="basic" onFinish={onSubmit}> <Form.Item name="title" rules={[ { required: true, message: "Please input your title!" } ]} > <Text editable>{title}</Text> </Form.Item> {data.map((d) => ( <SecForm /> ))} </Form>
子组件代码
const SecForm = () => { return ( <> <Form.Item label="target" name="target" rules={[ { required: true, message: "Please input your target!" } ]} > <Input placeholder="Target" /> </Form.Item> </> ); };
问题原因
所有循环生成的SecForm子组件中,Form.Item的name属性都设置为"target",导致它们全部绑定到Form状态中的同一个target字段。因此修改任意一个输入框,都会同步更新这个共享字段的值,进而让所有输入框显示相同内容。
简单解决方案
给每个子组件的Form.Item设置唯一的name标识,通过父组件传递数据的唯一id(或循环索引)给子组件,子组件用这个标识来区分不同的字段。
修改后的代码
父组件:传递唯一标识
<Form id="myForm" name="basic" onFinish={onSubmit}> <Form.Item name="title" rules={[ { required: true, message: "Please input your title!" } ]} > <Text editable>{title}</Text> </Form.Item> {data.map((d, index) => ( // 用数据id或索引作为唯一标识,同时设置key <SecForm key={d.id || index} itemId={d.id || index} /> ))} </Form>
子组件:使用唯一标识设置name
const SecForm = ({ itemId }) => { return ( <> <Form.Item label="target" // 用数组形式定义name,Form会将其解析为嵌套字段路径 name={["target", itemId]} rules={[ { required: true, message: "Please input your target!" } ]} > <Input placeholder="Target" /> </Form.Item> </> ); };
补充说明
- 也可以用字符串拼接的方式设置name,比如
name={target-${itemId}},但数组形式更适合后续以嵌套结构获取表单值(比如通过form.getFieldValue("target")得到一个包含所有子项的对象)。 - 循环渲染组件时务必设置
key,避免React渲染异常,这里用数据的id或索引均可,优先使用数据自身的唯一id。
内容的提问来源于stack exchange,提问作者Sai Krishnadas
相关产品推荐
相关产品推荐

