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

React中Map函数仅传递最后索引数据至删除函数问题排查

问题根源

你遇到的删除功能失效(只能获取最后一个索引数据),核心原因是循环内重复渲染弹窗且共享状态,加上闭包的变量引用特性:

  • 每一行都渲染了一个AlertDialog,所有弹窗共用同一个alertOpen状态,打开时多个弹窗叠加,实际触发的是最后一个弹窗的回调;
  • 闭包捕获的player是变量引用,循环结束后player指向数组最后一个元素,导致handleDelete始终拿到最后一个玩家的ID。
  • 额外隐患:用index作为<tr>的key,排序后元素顺序变化会导致React渲染异常,建议替换为唯一的player.id。
修复方案

1. 新增状态存储待删除的玩家ID

在组件内添加状态,记录当前要删除的玩家ID:

const [alertOpen, setAlertOpen] = React.useState(false);
const [deletingPlayerId, setDeletingPlayerId] = React.useState<string | null>(null);

2. 修改删除按钮的点击逻辑

点击删除时先记录当前玩家ID,再打开弹窗:

<DeleteButton onClick={() => {
  setDeletingPlayerId(player.id);
  setAlertOpen(true);
}} />

3. 只保留一个弹窗组件

将AlertDialog移出循环,放在组件根节点内(所有行共用一个弹窗),并使用记录的deletingPlayerId执行删除:

return (
  <>
    {stableSort(searchValue ? filteredPlayers : players, compare).map((player) => (
      <tr key={player.id}> {/* 替换key为player.id */}
        {/* 原有表格单元格代码保持不变 */}
        <td>
          <Box sx={{ display: "flex", gap: 2, alignItems: "flex-end", justifyContent: "flex-end" }}>
            <ExportButton />
            <DeleteButton onClick={() => {
              setDeletingPlayerId(player.id);
              setAlertOpen(true);
            }} />
          </Box>
        </td>
      </tr>
    ))}
    {/* 唯一的弹窗组件 */}
    <AlertDialog 
      open={alertOpen} 
      setOpen={setAlertOpen} 
      onAcceptClick={() => {
        if (deletingPlayerId) {
          handleDelete(deletingPlayerId, filteredPlayers, players, setPlayers, setFilteredPlayers);
          setDeletingPlayerId(null); // 删除后清空状态
        }
      }} 
    />
  </>
);

4. 可选:检查排序函数

如果回退版本后仍有问题,可确认stableSort和compare函数是否正确处理数组,确保排序后的数组元素ID和原数组一致,避免因排序导致的ID匹配异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:55:40