React子组件动态表单数据传至父组件 提交时打印全量数据
React 父子表单状态同步重构方案
原代码核心问题
- 状态结构矛盾:
formData初始值为对象,但动态增删表单项的逻辑按数组操作,数据类型不统一导致更新逻辑完全失效 - 事件参数缺失:父组件输入框变更方法要求传入表单项索引+事件对象,但子组件调用时仅传了事件对象,无法定位要更新的具体动态项
- 渲染逻辑缺失:子组件未对动态表单数组做遍历渲染,点击Add按钮后不会新增显示输入组
- 无效代码报错:父组件模板中直接写入
{setFormData},会把state更新函数渲染到页面触发运行时错误 - 状态耦合:固定基础字段(url、endpoint)和动态多组参数字段混存,更新时容易互相覆盖
重构后代码
父组件 ParamsForm.js
import React, { useState } from 'react' import styles from '../style.module.css' import OperationsFormTest from './OperationsFormTest' const ParamsForm = () => { const [isToggled, setIsToggled] = useState(false) // 拆分状态:基础表单固定字段单独存储 const [baseForm, setBaseForm] = useState({ url: '', endpoint: '' }) // 动态表单字段单独存为数组,每一项对应一组参数输入 const [pathParams, setPathParams] = useState([ { name: '', description: '', type: 'Any', required: '' } ]) // 基础表单输入更新 const handleBaseInputChange = (e) => { const { name, value } = e.target setBaseForm(prev => ({ ...prev, [name]: value })) } // 动态表单单字段更新 const handlePathParamChange = (index, e) => { const { name, value } = e.target setPathParams(prev => { const updated = [...prev] updated[index][name] = value return updated }) } // 新增一组动态表单项 const handleAddPathParam = () => { setPathParams(prev => [...prev, { name: '', description: '', type: 'Any', required: '' }]) } // 删除指定索引的动态表单项 const handleRemovePathParam = (index) => { setPathParams(prev => prev.filter((_, i) => i !== index)) } const handleSubmit = (e) => { e.preventDefault() // 合并全量表单数据 const fullFormData = { ...baseForm, pathParams: pathParams } console.log('全量表单数据:', fullFormData) } return ( <div className={styles.paramFormsContainer}> <form onSubmit={handleSubmit}> <input type='text' name='url' placeholder='Url..' value={baseForm.url} onChange={handleBaseInputChange} /> <input type='text' name='endpoint' placeholder='Endpoint...' value={baseForm.endpoint} style={{flex : 1 }} onChange={handleBaseInputChange} /> <button type='button' onClick={() => setIsToggled(!isToggled)} className={styles.pathParamFormsBtn} > Path Params </button> {isToggled && ( <OperationsFormTest paramList={pathParams} onParamChange={handlePathParamChange} onAdd={handleAddPathParam} onRemove={handleRemovePathParam} /> )} <br/><br/> <button type='submit'>Submit</button> </form> </div> ) } export default ParamsForm
子组件 OperationsFormTest.js
import React from 'react' import styles from '../style.module.css' const OperationsFormTest = ({ paramList, onParamChange, onAdd, onRemove }) => { return ( <div> <div className={styles.pathParamsFormParentContainer}> {/* 遍历动态参数数组,渲染每一组输入项 */} {paramList.map((param, index) => ( <div key={index} className={styles.pathParamsFormChildContainer}> <label>Name : </label> <input name='name' type='text' placeholder='Name..' value={param.name} onChange={(e) => onParamChange(index, e)} /> <br/><br/> <label>Description : </label> <input name='description' type='text' placeholder='Description..' value={param.description} onChange={(e) => onParamChange(index, e)} /> <br/><br/> <select name='type' value={param.type} onChange={(e) => onParamChange(index, e)} > <option value="Any">Any</option> <option value="String">String</option> <option value="Boolean">Boolean</option> </select> <label>Required : </label> <input name='required' type='text' placeholder='Yes or No..' value={param.required} onChange={(e) => onParamChange(index, e)} /> <br/><br/> <button type='button' onClick={onAdd}>Add</button> {/* 至少保留一组输入项,避免删空数组报错 */} {paramList.length > 1 && ( <button type='button' onClick={() => onRemove(index)}>Remove</button> )} <br/><br/> </div> ))} </div> </div> ) } export default OperationsFormTest
实现说明
- 所有表单状态全部收归父组件管理,子组件只负责渲染和触发回调,完全符合状态提升的设计要求
- 固定字段和动态列表字段拆分存储,更新逻辑互不干扰
- 子组件通过遍历
paramList渲染多组表单项,点击Add会自动新增输入组,点击Remove可删除对应项 - 提交时自动合并基础字段和动态参数列表,控制台可打印完整的表单数据
- 修复了原代码中事件参数不匹配、状态类型错误、无效代码渲染、下拉选框缺value属性等问题
内容的提问来源于stack exchange,提问作者nOhAr
相关产品推荐
相关产品推荐

