React打地鼠游戏中setInterval触发加速问题的原因及解决方案
问题原因及解决方案
问题原因
- 定时器重复创建:
lightUp的依赖数组包含status,每次调用setStatus更新状态后,lightUp都会生成新的函数实例。而useEffect的依赖包含status和lightUp,这会导致每次状态更新或lightUp重建时,都会触发useEffect执行lightUp,进而创建新的定时器,旧定时器未被正确清理,最终多个定时器同时运行,导致触发速度加快。 - 清理函数错误:创建的是
setInterval定时器,但清理时误用了clearTimeout,导致旧定时器无法被彻底清除。 - 时间间隔不符合需求:原代码设置的是1000毫秒(1秒),与期望的每2秒触发一次不符。
修复后的代码
function Grid({ number }) { const [status, setStatus] = useState(0); const array = Array(number).fill(); const lightUp = useCallback(() => { // 调整为2000毫秒,满足每2秒触发的需求 const timeId = setInterval(() => { // 生成与GridItem索引匹配的随机数(0到number-1) const item_id = Math.floor(Math.random() * number); console.log(item_id); setStatus(item_id); }, 2000); // 修复为clearInterval清理定时器 return () => clearInterval(timeId); }, [number]); // 仅当number变化时重新创建lightUp useEffect(() => { const cleanup = lightUp(); // 组件卸载或依赖更新时执行清理 return cleanup; }, [lightUp]); // 仅当lightUp变化时触发Effect return ( <div className='grid'> {array.map((e, idx) => { return <GridItem status={status} key={idx} index={idx} />; })} </div> ); } export default Grid;
关键调整说明
- 优化依赖逻辑:将
lightUp的依赖数组改为[number],仅当网格数量变化时才重新创建函数,避免因status更新导致的重复生成。 - 修复定时器清理:用
clearInterval替代clearTimeout,确保旧定时器能被正确清除,避免多个定时器同时运行。 - 匹配需求时间间隔:将
setInterval的触发时间改为2000毫秒,符合每2秒点亮一个网格的需求。 - 规范Effect清理:直接返回
lightUp的清理函数,确保组件卸载或依赖更新时,旧定时器被及时清理,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Coder_Nick
相关产品推荐
相关产品推荐

