React表单提交时如何获取动态/多字段的输入值?
解决方案
提供两种无第三方依赖的实现方案,可根据你的改造需求选择:
方案1:状态提升(推荐,长期维护更友好)
将动态字段的状态从子组件移到表单所在的父组件维护,提交时直接读取状态即可,符合React单向数据流的标准设计。
改造步骤
- 调整动态字段组件为受控组件,从props接收状态和操作方法:
const ItemNameTextFields = ({itemNames, onInputChange, onAddField}) => { return ( itemNames.map((itemName, i) => ( <Box component='span' key={`item_${i}`} sx={{display: 'flex', flexWrap: 'wrap'}}> <TextField value={itemName} onChange={e => onInputChange(i, e)} label={`Item ${i+1}`} name={`item_${i}`} className={classes.itemName} /> {itemNames.length-1 === i && <Button endIcon={<Icon icon={plusCircleOutline} />} onClick={onAddField} > <small>Add another</small> </Button> } </Box> )) ); }
- 父组件维护状态,提交时直接取值:
// 父组件内声明动态字段的状态 const [itemNames, setItemNames] = React.useState(['']); const addItemNameField = () => setItemNames([...itemNames, '']); const handleInputChange = (i, e) => { const values = [...itemNames]; values[i] = e.target.value; setItemNames(values); } const handleSubmit = e => { e.preventDefault(); let obj = { name: e.target['name'].value || '', // 直接取状态作为items数组,可加filter(Boolean)过滤空项 items: itemNames.filter(Boolean) }; // 若需要单独item_x的字段格式,添加以下逻辑即可 // itemNames.forEach((val, idx) => obj[`item_${idx+1}`] = val); console.log(obj); } // 渲染时传递props <form onSubmit={handleSubmit}> {/* 其他表单项 */} <ItemNameTextFields itemNames={itemNames} onInputChange={handleInputChange} onAddField={addItemNameField} /> <button type="submit">提交</button> </form>
方案2:FormData直接读取(改造成本极低)
如果不想调整现有组件的状态结构,可以直接通过FormData读取表单内所有带item_前缀的字段值,不需要修改子组件代码。
改造步骤
直接修改提交逻辑即可:
const handleSubmit = e => { e.preventDefault(); const formData = new FormData(e.target); let obj = { name: e.target['name'].value || '', items: [] }; // 遍历所有表单项匹配动态字段 for (const [fieldName, fieldValue] of formData.entries()) { if (fieldName.startsWith('item_')) { // 要数组格式直接push obj.items.push(fieldValue); // 要单独item_x格式直接赋值: // obj[fieldName] = fieldValue; } } console.log(obj); }
注:Material UI的TextField会自动把
name属性透传给原生input,FormData可以正常识别读取。
内容的提问来源于stack exchange,提问作者kougami
相关产品推荐
相关产品推荐

