Expo应用触发后setInterval运行速度翻倍问题求助
问题分析与解决方案
核心问题
你遇到的现象本质是多个定时器实例同时在运行。当触发triggeredInStep.current清除当前定时器后,之前未被清理的旧定时器仍在后台执行,导致后续步骤的状态更新频率翻倍(两个定时器同时每100ms更新一次)。
代码中的隐患
- 没有在创建新定时器前清除旧定时器:如果这段创建
stepInterval的代码会在组件重新渲染时重复执行(比如依赖的状态变化触发渲染),就会不断生成新的定时器,旧的定时器没被清理就会一直运行。 - 定时器ID仅存在于局部变量:
stepInterval是局部变量,组件重新渲染后会丢失旧的定时器ID,无法清除之前的实例。
修复方案
1. 用Ref保存定时器ID,确保每次创建前清除旧定时器
import { useRef } from 'react'; // 在组件内定义ref保存定时器ID const stepIntervalRef = useRef(null); // 创建定时器前先清除旧的 if (stepIntervalRef.current) { clearInterval(stepIntervalRef.current); } stepIntervalRef.current = setInterval(() => { setStepCountdown((prev) => { if (triggeredInStep.current){ turnOffAllNodes(); console.log("Triggered in step"); clearInterval(stepIntervalRef.current); stepIntervalRef.current = null; // 清空ref if (currentStep < selectedSteps) { setDelayCountdown(selectedDelay); } return 0; } if (prev <= 0.1) { clearInterval(stepIntervalRef.current); stepIntervalRef.current = null; // 清空ref setIncorrectCount((prev) => prev + 1); console.log("Incorrect timeout, turning off all nodes and not triggered in step"); turnOffAllNodes(); if (currentStep < selectedSteps) { setDelayCountdown(selectedDelay); } return 0; } return Math.max(prev - 0.1, 0); }); }, 100);
2. 组件卸载时清除定时器
添加清理逻辑,防止组件卸载后定时器仍在运行:
import { useEffect } from 'react'; useEffect(() => { return () => { if (stepIntervalRef.current) { clearInterval(stepIntervalRef.current); } }; }, []);
3. 检查触发逻辑的时机
确认triggeredInStep.current的设置逻辑,避免在定时器清除前多次触发导致重复创建定时器。比如在设置triggeredInStep.current = true时,确保不会同时触发新的定时器创建。
验证方法
可以在创建定时器时打印日志,比如console.log('创建新定时器', stepIntervalRef.current),在清除时打印console.log('清除定时器', stepIntervalRef.current),观察是否有重复创建未清除的情况。
内容的提问来源于stack exchange,提问作者Damián Vallejo
相关产品推荐
相关产品推荐

