如何在React中创建嵌套分组表单并获取结构化提交值?
解决React嵌套表单层级结构化值问题
方法一:利用Antd Form的嵌套name路径(推荐)
Antd Form原生支持通过数组形式的name属性构建嵌套结构,无需额外自定义分组组件,直接让Form自动生成期望的嵌套对象。
示例代码
import { Form, Input, Button } from 'antd'; const NestedForm = () => { const onFinish = (values) => { console.log('提交的结构化值:', values); // 输出格式完全匹配需求: // { // group1: { // section1: { item1: 'xxx', item2: 'xxx' }, // section2: { item1: 'xxx', item2: 'xxx' } // }, // group2: { ... } // } }; return ( <Form onFinish={onFinish}> {/* Group 1 区域 */} <div className="form-group"> <h3>Group 1</h3> {/* Section 1 区域 */} <div className="form-section"> <h4>Section 1</h4> <Form.Item name={['group1', 'section1', 'item1']} label="Item 1" > <Input /> </Form.Item> <Form.Item name={['group1', 'section1', 'item2']} label="Item 2" > <Input /> </Form.Item> </div> {/* Section 2 区域 */} <div className="form-section"> <h4>Section 2</h4> <Form.Item name={['group1', 'section2', 'item1']} label="Item 1" > <Input /> </Form.Item> <Form.Item name={['group1', 'section2', 'item2']} label="Item 2" > <Input /> </Form.Item> </div> </div> {/* Group 2 区域 */} <div className="form-group"> <h3>Group 2</h3> {/* Section 1 区域 */} <div className="form-section"> <h4>Section 1</h4> <Form.Item name={['group2', 'section1', 'item1']} label="Item 1" > <Input /> </Form.Item> <Form.Item name={['group2', 'section1', 'item2']} label="Item 2" > <Input /> </Form.Item> </div> {/* Section 2 区域 */} <div className="form-section"> <h4>Section 2</h4> <Form.Item name={['group2', 'section2', 'item1']} label="Item 1" > <Input /> </Form.Item> <Form.Item name={['group2', 'section2', 'item2']} label="Item 2" > <Input /> </Form.Item> </div> </div> <Form.Item> <Button type="primary" htmlType="submit">提交表单</Button> </Form.Item> </Form> ); }; export default NestedForm;
原理说明
Antd Form会解析数组形式的name,自动将字段值组装成嵌套对象,提交时直接获取结构化数据,无需额外处理。
方法二:自定义Context实现分组层级自动拼接
如果需要保留你最初的FormGroup/FormItem组件结构,可以通过React Context传递层级路径,让子组件自动拼接完整的字段名,完全贴合你的原始代码结构。
示例代码
import { createContext, useContext } from 'react'; import { Form, Input, Button } from 'antd'; // 创建层级上下文 const FormGroupContext = createContext([]); // 自定义FormGroup组件,传递当前层级路径 const FormGroup = ({ name, children }) => { const parentPath = useContext(FormGroupContext); const currentPath = [...parentPath, name]; return ( <FormGroupContext.Provider value={currentPath}> <div>{children}</div> </FormGroupContext.Provider> ); }; // 自定义FormItem组件,自动拼接完整字段名 const FormItem = ({ name, label, children }) => { const parentPath = useContext(FormGroupContext); const fullName = [...parentPath, name]; return ( <Form.Item name={fullName} label={label}> {children} </Form.Item> ); }; const NestedForm = () => { const onFinish = (values) => { console.log('提交的结构化值:', values); }; return ( <Form onFinish={onFinish}> <FormGroup name="group1"> <h3>Group 1</h3> <FormGroup name="section1"> <h4>Section 1</h4> <FormItem name="item1" label="Item 1"> <Input /> </FormItem> <FormItem name="item2" label="Item 2"> <Input /> </FormItem> </FormGroup> <FormGroup name="section2"> <h4>Section 2</h4> <FormItem name="item1" label="Item 1"> <Input /> </FormItem> <FormItem name="item2" label="Item 2"> <Input /> </FormItem> </FormGroup> </FormGroup> <FormGroup name="group2"> <h3>Group 2</h3> <FormGroup name="section1"> <h4>Section 1</h4> <FormItem name="item1" label="Item 1"> <Input /> </FormItem> <FormItem name="item2" label="Item 2"> <Input /> </FormItem> </FormGroup> <FormGroup name="section2"> <h4>Section 2</h4> <FormItem name="item1" label="Item 1"> <Input /> </FormItem> <FormItem name="item2" label="Item 2"> <Input /> </FormItem> </FormGroup> </FormGroup> <Form.Item> <Button type="primary" htmlType="submit">提交表单</Button> </Form.Item> </Form> ); }; export default NestedForm;
原理说明
通过Context在FormGroup之间传递当前的层级路径,FormItem自动拼接父级路径和自身name,最终Antd Form根据完整的嵌套name生成结构化数据,完全匹配你的需求。
方法三:手动组装结构化数据(兼容现有代码)
如果不想修改现有组件结构,也可以在表单提交时,根据约定的字段名手动组装嵌套对象。
示例代码
import { Form, Input, Button } from 'antd'; const NestedForm = () => { const form = Form.useForm(); const onFinish = () => { const rawValues = form.getFieldsValue(); // 手动映射为嵌套结构 const structuredValues = { group1: { section1: { item1: rawValues['group1-section1-item1'], item2: rawValues['group1-section1-item2'], }, section2: { item1: rawValues['group1-section2-item1'], item2: rawValues['group1-section2-item2'], }, }, group2: { section1: { item1: rawValues['group2-section1-item1'], item2: rawValues['group2-section1-item2'], }, section2: { item1: rawValues['group2-section2-item1'], item2: rawValues['group2-section2-item2'], }, }, }; console.log('组装后的结构化值:', structuredValues); }; return ( <Form form={form} onFinish={onFinish}> <div className="form-group"> <h3>Group 1</h3> <div className="form-section"> <h4>Section 1</h4> <Form.Item name="group1-section1-item1" label="Item 1"> <Input /> </Form.Item> <Form.Item name="group1-section1-item2" label="Item 2"> <Input /> </Form.Item> </div> <div className="form-section"> <h4>Section 2</h4> <Form.Item name="group1-section2-item1" label="Item 1"> <Input /> </Form.Item> <Form.Item name="group1-section2-item2" label="Item 2"> <Input /> </Form.Item> </div> </div> {/* Group 2 部分代码与Group 1类似 */} <div className="form-group"> <h3>Group 2</h3> <div className="form-section"> <h4>Section 1</h4> <Form.Item name="group2-section1-item1" label="Item 1"> <Input /> </Form.Item> <Form.Item name="group2-section1-item2" label="Item 2"> <Input /> </Form.Item> </div> <div className="form-section"> <h4>Section 2</h4> <Form.Item name="group2-section2-item1" label="Item 1"> <Input /> </Form.Item> <Form.Item name="group2-section2-item2" label="Item 2"> <Input /> </Form.Item> </div> </div> <Form.Item> <Button type="primary" htmlType="submit">提交表单</Button> </Form.Item> </Form> ); }; export default NestedForm;
原理说明
通过给每个字段设置包含层级信息的唯一name(如group1-section1-item1),提交后手动将扁平的rawValues映射为嵌套对象,适合快速兼容现有代码的场景。
内容的提问来源于stack exchange,提问作者Yassine Hamadou
相关产品推荐
相关产品推荐

