使用FormData提交多条API数据时仅能获取单条数据的问题
问题:FormData提交多条记录时仅能获取最后一条数据
通过API获取到包含sequence为1和2的两条记录,渲染成可编辑表单后提交,FormData中仅存在sequence为2的数据,无法将全部记录传入updateAPDB接口完成更新。
核心原因
表单中所有同类型输入框的name属性完全重复,FormData收集数据时,相同name的字段会被最后一个元素的值覆盖,最终只能保留最后一条记录的内容。
解决方案
步骤1:给输入框添加唯一标识的name
基于每条记录的acd_con_seq(唯一序列值),给每个输入框的name添加后缀,确保字段名唯一,比如applicationId_1、applicationId_2。
步骤2:在action中整理数据结构
将FormData中的零散字段重新组合成数组格式,匹配原有的多条记录结构,再传给更新接口。
修改后的代码示例
表单渲染代码
<div className="APDB_table-wrapper"> <table className="table-Result"> <tbody> <tr className="table-Result-Row"> <th className="table-Result-Header">Application ID</th> <th className="table-Result-Header">Application Name</th> <th className="table-Result-Header">GSID</th> <th className="table-Result-Header">Sequence</th> <th className="table-Result-Header">Application DL</th> <th className="table-Result-Header">Manager DL</th> <th className="table-Result-Header"> Application Owner DL </th> <th className="table-Result-Header">DataCenter</th> <th className="table-Result-Header">QA SFTP ID</th> <th className="table-Result-Header">QA Password</th> <th className="table-Result-Header">PROD SFTP ID</th> <th className="table-Result-Header">PROD Password</th> <th className="table-Result-Header">Updated User</th> </tr> {Result.map((item) => ( <tr key={item.acd_con_seq} className="table-Result-Data"> <td> <input type="text" name={`applicationId_${item.acd_con_seq}`} value={item.acd_ap_id} readOnly /> </td> <td> <input type="text" name={`applicationName_${item.acd_con_seq}`} value={item.acd_ap_nm} readOnly /> </td> <td> <input type="text" name={`gsid_${item.acd_con_seq}`} value={item.acd_ap_gsid} readOnly /> </td> <td> <input type="text" name={`Sequence_${item.acd_con_seq}`} value={item.acd_con_seq} readOnly /> </td> <td> <input type="text" name={`applicationDl_${item.acd_con_seq}`} onChange={(e) => { item.acd_appl_dl = e.target.value; }} defaultValue={item.acd_appl_dl} /> </td> <td> <input type="email" name={`leadManagerDl_${item.acd_con_seq}`} defaultValue={item.acd_lead_manager_dl} onChange={(e) => { item.acd_lead_manager_dl = e.target.value; }} /> </td> <td> <input type="email" name={`systemOwnerNameDl_${item.acd_con_seq}`} defaultValue={item.acd_system_owner_name_dl} onChange={(e) => { item.acd_system_owner_name_dl = e.target.value; }} /> </td> <td> <input type="text" name={`dataCenterName_${item.acd_con_seq}`} defaultValue={item.acd_dc_name} onChange={(e) => { item.acd_dc_name = e.target.value; }} /> </td> <td> <input type="text" name={`qaSftpId_${item.acd_con_seq}`} defaultValue={item.acd_qa_sftp_id} onChange={(e) => { item.acd_qa_sftp_id = e.target.value; }} /> </td> <td> <input type="text" name={`qaSftpPwd_${item.acd_con_seq}`} defaultValue={item.acd_qa_sftp_pwd} onChange={(e) => { item.acd_qa_sftp_pwd = e.target.value; }} /> </td> <td> <input type="text" name={`prodSftpId_${item.acd_con_seq}`} defaultValue={item.acd_prod_sftp_id} onChange={(e) => { item.acd_prod_sftp_id = e.target.value; }} /> </td> <td> <input type="text" name={`prodSftpPwd_${item.acd_con_seq}`} defaultValue={item.acd_prod_sftp_pwd} onChange={(e) => { item.acd_prod_sftp_pwd = e.target.value; }} /> </td> <td> <input type="text" name={`updatedUser_${item.acd_con_seq}`} defaultValue={item.acd_upd_usr} onChange={(e) => { item.acd_upd_usr = e.target.value; }} /> </td> </tr> ))} </tbody> </table> </div> <input type="submit" className="submit_Update" /> </div> </Form>
表单提交action函数
export async function action({ request }) { console.log("function called"); const formData = await request.formData(); const formEntries = Array.from(formData.entries()); // 整理成数组格式的记录 const records = {}; formEntries.forEach(([key, value]) => { // 拆分字段名和sequence const [fieldName, seq] = key.split("_"); if (!records[seq]) { records[seq] = {}; } // 映射回原数据字段名 switch(fieldName) { case "applicationId": records[seq].acd_ap_id = value; break; case "applicationName": records[seq].acd_ap_nm = value; break; case "gsid": records[seq].acd_ap_gsid = value; break; case "Sequence": records[seq].acd_con_seq = value; break; case "applicationDl": records[seq].acd_appl_dl = value; break; case "leadManagerDl": records[seq].acd_lead_manager_dl = value; break; case "systemOwnerNameDl": records[seq].acd_system_owner_name_dl = value; break; case "dataCenterName": records[seq].acd_dc_name = value; break; case "qaSftpId": records[seq].acd_qa_sftp_id = value; break; case "qaSftpPwd": records[seq].acd_qa_sftp_pwd = value; break; case "prodSftpId": records[seq].acd_prod_sftp_id = value; break; case "prodSftpPwd": records[seq].acd_prod_sftp_pwd = value; break; case "updatedUser": records[seq].acd_upd_usr = value; break; default: break; } }); // 转换成数组传给接口 const dataArray = Object.values(records); console.log(dataArray); const newData = await updateAPDB(dataArray); if (newData !== "1") { return null; } else { return redirect(`/webpage`); } }
可选优化:数组式命名
如果使用React Hook Form、Remix等支持表单数组的框架,可直接用数组格式的name,比如:
<input type="text" name={`records[${index}].applicationId`} value={item.acd_ap_id} readOnly />
这种方式下FormData会自动整理成数组结构,action中无需手动拆分字段,直接解析即可。
内容的提问来源于stack exchange,提问作者user23154524
相关产品推荐
相关产品推荐

