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
相关产品推荐
相关产品推荐

