You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

表单提交仅获取最后一条数组对象数据的问题及解决方法

问题描述

我从API获取多条数据,通过map渲染成带可编辑输入框的表格,期望用户修改后提交所有变更给API更新。但提交表单时只能获取到Result中最后一条记录的值,无法拿到全部数据。当前渲染代码和表单处理代码如下:

渲染表格的代码

{Result.map((item,index) => (
  <tr key={index} className="table-Result-Data">
    <td>
      <input
        type="text"
        name="applicationId"
        value={item.acd_ap_id}
        readOnly
      />
    </td>
    <td>
      <input
        type="text"
        name="applicationName"
        value={item.acd_ap_nm}
        readOnly
      />
    </td>
    <td>
      <input
        type="text"
        name="gsid"
        value={item.acd_ap_gsid}
        readOnly
      />
    </td>
    <td>
      <input
        type="text"
        name="Sequence"
        value={item.acd_con_seq}
        readOnly
      />
    </td>
    <td>
      <input
        type="text"
        name="applicationDl"
        onChange={(e) => {
          item.acd_appl_dl = e.target.value;
        }}
        defaultValue={item.acd_appl_dl}
      />
    </td>
    <td>
      <input
        type="email"
        name="leadManagerDl"
        defaultValue={item.acd_lead_manager_dl}
        onChange={(e) => {
          item.acd_lead_manager_dl = e.target.value;
        }}
      />
    </td>
    <td>
      <input
        type="email"
        name="systemOwnerNameDl"
        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"
        defaultValue={item.acd_dc_name}
        onChange={(e) => {
          item.acd_dc_name = e.target.value;
        }}
      />
    </td>
    <td>
      <input
        type="text"
        name="qaSftpId"
        defaultValue={item.acd_qa_sftp_id}
        onChange={(e) => {
          item.acd_qa_sftp_id = e.target.value;
        }}
      />
    </td>
    <td>
      <input
        type="text"
        name="qaSftpPwd"
        defaultValue={item.acd_qa_sftp_pwd}
        onChange={(e) => {
          item.acd_qa_sftp_pwd = e.target.value;
        }}
      />
    </td>
    <td>
      <input
        type="text"
        name="prodSftpId"
        defaultValue={item.acd_prod_sftp_id}
        onChange={(e) => {
          item.acd_prod_sftp_id = e.target.value;
        }}
      />
    </td>
    <td>
      <input
        type="text"
        name="prodSftpPwd"
        defaultValue={item.acd_prod_sftp_pwd}
        onChange={(e) => {
          item.acd_prod_sftp_pwd = e.target.value;
        }}
      />
    </td>
    <td>
      <input
        type="text"
        name="updatedUser"
        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" />

表单处理代码

export async function action({ request }) {
  console.log(" APDB functioncalled");
  const formData = await request.formData();
  console.log(formData)
  const data = Object.fromEntries(formData);
  console.log(data)
}
问题原因

不是map函数导致的问题,核心原因有两个:

  1. 输入框name属性重复:所有行的同类型输入框使用了相同的name(比如applicationId、applicationDl),表单提交时,同名的输入值会被覆盖,最终只保留最后一行的输入值。
  2. 直接修改原数据不符合React规范:直接修改API返回的item对象,这种方式不会触发组件重新渲染,无法准确跟踪所有数据的变更状态,同时也会导致表单提交时无法正确收集所有行的数据。
解决方案

方案一:修改输入框name属性为数组格式(适合原生表单提交)

给每个输入框的name添加行索引,使用数组格式命名,表单提交时会自动将所有行的数据整理为数组结构:

{Result.map((item, index) => (
  <tr key={index} className="table-Result-Data">
    <td>
      <input
        type="text"
        name={`records[${index}].applicationId`}
        value={item.acd_ap_id}
        readOnly
      />
    </td>
    <td>
      <input
        type="text"
        name={`records[${index}].applicationName`}
        value={item.acd_ap_nm}
        readOnly
      />
    </td>
    {/* 其他输入框同理,修改name为`records[${index}].字段名`格式 */}
    <td>
      <input
        type="text"
        name={`records[${index}].applicationDl`}
        defaultValue={item.acd_appl_dl}
        onChange={(e) => {
          item.acd_appl_dl = e.target.value;
        }}
      />
    </td>
    {/* 剩余输入框重复上述修改 */}
  </tr>
))}

此时在action函数中,可以用qs库解析formData,直接得到所有行的数组:

import qs from 'qs';

export async function action({ request }) {
  const formData = await request.formData();
  const parsedData = qs.parse(formData.toString());
  console.log(parsedData.records); // 所有行的完整数据数组
}

方案二:使用React状态管理表格数据(推荐,符合React状态驱动理念)

将API返回的Result存入组件状态,通过状态更新跟踪数据变更,提交时直接将状态数据发送给API:

  1. 初始化状态:
import { useState, useEffect } from 'react';

function YourComponent() {
  const [tableData, setTableData] = useState([]);

  useEffect(() => {
    // 模拟API请求获取数据
    const fetchData = async () => {
      const res = await fetch('/your-api-url');
      const result = await res.json();
      setTableData(result);
    };
    fetchData();
  }, []);
  1. 渲染受控输入框:
    将输入框改为受控组件,绑定状态值,onChange时更新对应行的数据:
{tableData.map((item, index) => (
  <tr key={index} className="table-Result-Data">
    <td>
      <input
        type="text"
        value={item.acd_ap_id}
        readOnly
      />
    </td>
    <td>
      <input
        type="text"
        value={item.acd_appl_dl}
        onChange={(e) => {
          setTableData(prev => {
            const newData = [...prev];
            newData[index] = {
              ...newData[index],
              acd_appl_dl: e.target.value
            };
            return newData;
          });
        }}
      />
    </td>
    {/* 其他输入框同理,替换value和onChange逻辑 */}
  </tr>
))}
  1. 提交数据:
    提交时直接将tableData作为请求体发送给API:
const handleSubmit = async () => {
  const res = await fetch('/your-update-api', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(tableData)
  });
  const result = await res.json();
  // 处理提交结果
};

// 替换原submit按钮
<button type="button" className="submit_Update" onClick={handleSubmit}>提交</button>
总结

优先选择方案二,它符合React状态驱动的设计理念,能更准确地跟踪数据变更,也避免了表单name属性冲突的问题。如果必须使用原生表单提交,则采用方案一,通过修改name属性格式确保所有行的数据被正确收集。

内容的提问来源于stack exchange,提问作者user23154524

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 12:09:51