React中执行删除操作后map渲染的表格未更新问题
问题原因
- 核心原因是违反了React的状态不可变原则:React判断状态是否需要更新触发重渲染,靠的是对状态值的浅比较。你代码里用的
splice方法会直接原地修改原数组,修改后传给setList的数组和原有状态的数组是同一个内存引用,React会认为状态没有发生变化,自然不会触发重渲染。 - 额外逻辑错误:你执行
splice操作的目标是组件内定义的普通常量trains,不是状态变量trainList,本身就没有对正确的状态源做操作。 - 潜在隐患:按钮的
id属性拿到的是字符串类型的索引,直接传入splice虽然会被JS隐式转换为数字,但显式转换类型能避免很多边界问题。
修复方法
不要直接修改原数组,基于现有状态生成一个全新的数组,再传给状态更新函数。推荐用filter方法直接过滤掉要删除的项,该方法天然返回新数组不会修改原数组,写法也更简洁。
修复后的完整代码:
function TrainPage(){ const [trainList, setList] = useState([ {name: "Thomas", dest: "New York", first: "05:00", freq: 30}, {name: "Duncan", dest: "Boston", first: "06:00", freq: 45} ]); function remove(event){ // 拿到要删除的索引,转成数字类型 const deleteIndex = Number(event.target.id); // 用filter生成新数组,过滤掉索引匹配的项,不修改原数组 const newList = trainList.filter((_, index) => index !== deleteIndex); setList(newList); } return( <div> <table> <tr> <th>Train Name</th> <th>Destination</th> <th>Frequency</th> <th>Minutes Away</th> <th>Next Arrival</th> </tr> {trainList.map((train, index) => ( <tr key={index}> <td>{train.name}</td> <td>{train.dest}</td> <td>{train.freq}mins</td> <td></td> <td></td> <td> <button onClick={remove} data-toggle='tooltip' data-placement='left' title='delete train' id={index} > x </button> </td> </tr> ))} </table> </div> ) }
补充:列表渲染的时候建议给每一项加唯一的
key属性,上面代码暂时用index兜底,如果列车数据有唯一ID(比如车次编号),用唯一ID当key比索引更稳妥,能避免列表顺序变动时的渲染异常。
内容的提问来源于stack exchange,提问作者DennisM
相关产品推荐
相关产品推荐

