ReactJS中API删除弹窗确认异常:点击总是删除最后一项
问题根源
- 弹窗重复渲染+共享状态:你在
products.map()循环内部渲染弹窗,每个产品对应一个弹窗,所有弹窗共享同一个openDeleteModal状态。打开弹窗时多个弹窗叠加显示,点击确认按钮时,由于闭包特性,product变量会指向循环最后一次迭代的产品,导致总是删除最后一项。 - 无目标产品存储:没有单独记录当前要删除的目标产品,无法精准传递删除对象。
解决方案
1. 调整状态,存储目标删除产品
替换原来的弹窗状态,改为存储当前要删除的产品(初始为null):
// 替换原有的openDeleteModal相关状态 const [deleteTarget, setDeleteTarget] = useState(null); const closeDeleteModal = () => { setDeleteTarget(null); document.body.style.overflow = "unset"; }; // 打开弹窗时传入当前产品 const showDeleteModal = (product) => { setDeleteTarget(product); document.body.style.overflow = "hidden"; // 可选:禁用背景滚动 };
2. 弹窗移到列表外部,只渲染一次
把弹窗组件从循环内移出,整个页面仅保留一个弹窗,通过deleteTarget判断是否显示:
{/* 弹窗放在产品列表的外层,只渲染一次 */} {deleteTarget && ( <div className="delete-modal"> <div className="delete-modal-box"> <div className="delete-modal-content"> <p className="delete-modal-content-p"> Are you sure to delete {deleteTarget.name}? {/* 可选:显示产品名称,提升体验 */} </p> <div className="delete-modal-btn"> <button onClick={closeDeleteModal} className="delete-modal-btn-close"> Close </button> <button onClick={() => { deleteHandler(deleteTarget); closeDeleteModal(); }} className="delete-modal-btn-yes" > Yes </button> </div> </div> </div> </div> )}
3. 修改删除按钮的点击事件
在产品列表的删除按钮中,传入当前产品到弹窗触发函数:
<DeleteOutline className="product-delete" onClick={() => showDeleteModal(product)} // 传入当前要删除的产品 />
4. 清理循环内的弹窗代码
删除products.map()循环内部的弹窗代码,避免重复渲染。
额外优化:替换key值
不要用index作为列表项的key,改用产品唯一IDproduct._id,避免列表更新时出现渲染异常:
{products?.map((product) => ( <tr className="product-item-list" key={product._id}> {/* 用产品ID作为key */} {/* ... 其他列表内容不变 */} </tr> ))}
验证修改
完成以上调整后,点击任意产品的删除按钮,弹窗会正确绑定当前目标产品,确认后即可删除对应的产品。
内容的提问来源于stack exchange,提问作者MaxMan MX
相关产品推荐
相关产品推荐

