React StrictMode下useEffect与setInterval重复执行问题求解
解决StrictMode下useEffect定时器导致状态异常的问题
你的问题核心是直接修改React状态对象引发的异常,加上StrictMode在开发环境的双重渲染放大了这个问题。StrictMode的双重执行是开发环境的检测机制,生产环境不会触发,但我们需要让代码在开发环境也能正常工作,关键是修复状态不可变的问题。
原代码的问题点
在setQueueState的回调中,你直接修改了pre数组里的line[0].items:
line[0].items = line[0].items > 0 ? line[0].items - 1 : 0;
这违反了React状态不可变的原则——状态对象是只读的,直接修改会导致React无法正确追踪状态变化,在StrictMode的双重渲染下,这种突变会导致状态更新叠加,出现物品数量一次减2的情况。
修复后的代码
下面是遵循状态不可变原则的修改版本:
useEffect(() => { const interval = setInterval(() => { setQueueState((prev) => { return prev.map((line) => { if (line.length === 0) return []; // 创建新的首位人员对象,不修改原状态 const updatedFirst = { ...line[0], items: line[0].items > 0 ? line[0].items - 1 : 0 }; if (updatedFirst.items > 0) { // 组合新数组:更新后的首位 + 过滤后的后续人员 return [ updatedFirst, ...line.slice(1).filter(person => person.items > 0) ]; } else { // 移除首位,保留过滤后的后续人员 return [...line.slice(1).filter(person => person.items > 0)]; } }); }); }, 4000); return () => clearInterval(interval); }, []);
修复说明
- 状态不可变处理:每次更新状态时,都创建新的对象(
updatedFirst)和数组,完全不修改原有的prev状态对象,确保React能正确识别状态变化。 - StrictMode兼容性:修复后,即使StrictMode在开发环境双重执行useEffect,最终只会保留一个定时器,且状态更新逻辑是纯函数式的,不会出现叠加异常。
内容的提问来源于stack exchange,提问作者ludinj
相关产品推荐
相关产品推荐

