React Router v6中用Form与Actions实现动态输入字段的问题
解决react-router-dom动态表单字段的两个问题
问题分析
- 提交后仅获取单个兴趣:所有兴趣输入框的
name属性都是val,FormData中同名键只会保留最后一次输入值,无法收集数组。 - uncontrolled输入警告:添加新字段时,对象属性是
name和age,但输入框绑定的是item.val,初始值为undefined,导致输入从无控转为受控。
修改后的完整代码
import { Form } from "react-router-dom"; import { useState } from "react"; export const action = async ({ request }) => { const formData = await request.formData(); // 手动提取数组类型的表单字段 const data = { username: formData.get("username"), password: formData.get("password"), interest: formData.getAll("interest[]") // 用getAll获取所有同名值组成数组 }; console.log(data); return data; }; export default function Home() { const [interests, setInterests] = useState([{ val: "" }]); const handleFormChange = (event, index) => { let data = [...interests]; data[index].val = event.target.value; // 直接赋值val,不用取name,因为输入框name是给FormData用的 setInterests(data); }; const addFields = () => { // 添加和初始结构一致的对象,避免undefined值 setInterests([...interests, { val: "" }]); }; const removeFields = (index) => { let data = [...interests]; data.splice(index, 1); setInterests(data); }; return ( <div> <Form method="post" className="form"> <input type="text" name="username" placeholder="username" /> <input type="password" name="password" placeholder="password" /> {interests.map((item, index) => ( <div key={index}> <input type="text" name="interest[]" // 改成带[]的name,让FormData识别为数组 placeholder="interests" onChange={(event) => handleFormChange(event, index)} value={item.val} /> <button type="button" onClick={() => removeFields(index)}>Remove</button> </div> ))} <button type="button" onClick={addFields}>Add More..</button> <button type="submit">Submit</button> </Form> </div> ); }
关键改动说明
- 表单字段命名:将兴趣输入框的
name改为interest[],这样FormData会把所有该名称的输入值收集为集合,后续用getAll方法就能拿到完整数组。 - 修复uncontrolled警告:
addFields中添加的对象改为{ val: "" },确保每个输入框的value初始值为字符串,避免undefined导致的状态切换。 - FormData处理优化:不再用
Object.fromEntries直接转换,而是手动提取字段,对数组类型的字段使用formData.getAll()获取所有值,保证interest是数组格式。 - 简化change事件处理:因为输入框的
name是给FormData用的,状态更新时直接赋值val属性即可,无需通过event.target.name动态获取。
内容的提问来源于stack exchange,提问作者saimarshadd
相关产品推荐
相关产品推荐

