React Hooks结合useContext开发Todo应用删除任务误删最后一项问题咨询
问题根因分析
1. 核心问题:列表渲染时误用数组索引作为key
这是导致你现象的最主要原因:
React在对比虚拟DOM差异、更新真实DOM时,依赖列表项的key属性识别对应组件。如果你在遍历渲染Task组件时,错误将数组的索引index绑定为key,就会出现你描述的现象:
初始3个任务的索引为0、1、2,对应key为0、1、2,分别对应id=1、id=2、id=3的任务。当你删除id=1的任务后,剩余的2个任务索引变为0、1,对应key为0、1。React的diff算法会认为key=2的组件被删除,直接移除最后一个DOM节点,同时复用前两个key对应的组件。如果你的Task组件内部将传入的任务文本存在了本地state,仅在组件第一次挂载时赋值,后续props变更没有同步更新,就会出现页面显示的文本和实际state不一致的情况,看起来就像删除了最后一项。
2. 潜在优化点:状态更新的闭包陷阱
你当前的remove函数写法存在闭包问题,虽然你排查发现状态更新符合预期,但在异步场景或者多次连续调用时可能出现异常:你的remove函数直接引用了外层的todolist变量,取到的是函数创建时的旧状态值。
修复方案
- 遍历渲染
Task时,将key绑定为任务的唯一id,不要用数组索引:
// 错误写法 todolist.map((task, index) => <Task key={index} task={task} />) // 正确写法 todolist.map(task => <Task key={task.id} task={task} />)
- 优化
remove函数的状态更新写法,使用函数式更新获取最新的列表状态:
function remove(id){ setList(prevList => prevList.filter(t => t.id !== id)) }
- 检查
Task组件,优先直接使用props.task.text渲染文本,不要在组件内部用本地state存储传入的任务文本,避免props更新后不同步的问题。
内容的提问来源于stack exchange,提问作者Fayez Als
相关产品推荐
相关产品推荐

