React定时执行map重置任务优先级时数组被清空如何解决
问题原因分析
- 闭包陷阱导致获取的tasks状态是旧值:定时任务回调创建时就捕获了当前组件作用域下的
tasks值,后续组件重渲染更新tasks后,回调里拿到的仍然是创建时的旧值,无法匹配最新的任务列表。 - 重复创建多个定时任务:定时器创建逻辑没有放在
useEffect钩子中,组件每触发一次重渲染就会新建一个定时任务,多个任务同时触发就会导致console.log执行多次,多次调用setTasks时如果使用了不同闭包捕获的旧tasks值,就会出现状态被错误覆盖,最终甚至变成空数组的情况。 - 状态更新写法错误:修改依赖旧状态的新状态时,没有使用函数式更新写法,无法保证拿到最新的状态值。
修复方案
将定时器逻辑放入useEffect钩子,同时改用状态的函数式更新写法,修复后代码如下:
useEffect(() => { const clearPrioritiesJob = schedule.scheduleJob('0 0 0 * * *', () => { setTasks(prevTasks => { console.log(prevTasks) return prevTasks.map(task => ({ ...task, priority: false })) }); clearPrioritiesJob.cancel(); }); // 组件卸载时销毁定时器,避免内存泄漏 return () => clearPrioritiesJob.cancel(); }, [])
修复逻辑说明:
- 空依赖的
useEffect仅会在组件首次挂载时执行,保证只会创建一个定时任务 setTasks改用函数式更新,参数prevTasks永远取最新的任务列表,不受闭包影响- 新增useEffect销毁逻辑,组件卸载时主动取消定时器,避免异常触发
内容的提问来源于stack exchange,提问作者Lloyd Rajoo
相关产品推荐
相关产品推荐

