React中使用标志位实现切换按钮 状态切换不即时问题
问题根因
你的代码存在两个直接导致异常的问题:
- 状态和对应执行逻辑完全写反
你初始定义paused = true,代表页面初始加载时定时器处于暂停状态,但判断分支里paused === true对应的操作却是「保存剩余时间、清除定时器」的暂停逻辑——首次点击按钮本应触发继续运行,结果反而执行了暂停操作,状态从一开始就翻转错位。 - 状态存储方式不符合React运行机制
如果你把paused、holdValue定义在函数组件内部,每次组件重渲染都会把这两个变量重置为初始值,根本无法保留上一次交互后的状态;再加上setRemainingTime是异步更新,你先调用startTimer()再设置剩余时间,定时器启动时大概率拿到的是旧的时间值,最终表现就是需要多次点击才能触发预期的暂停/继续切换。
修复代码
用useRef存储跨重渲染稳定可变的暂停状态、暂存时间值,同时对齐状态判断和对应操作的逻辑,调整状态更新顺序避免时序问题:
///////PAUSE TIMER///////////////// // ref存储的值不会随组件重渲染重置,适合存定时器相关的瞬时状态 const pausedRef = useRef(true); const holdValueRef = useRef(0); function toggleTimer(){ if (pausedRef.current === true){ // 当前为暂停状态,点击后执行继续逻辑 pausedRef.current = false; // 先恢复剩余时间,再启动定时器,避免定时器拿到旧值 setRemainingTime(holdValueRef.current); startTimer(); } else { // 当前为运行状态,点击后执行暂停逻辑 pausedRef.current = true; // 先暂存当前剩余时间,再清除定时器 holdValueRef.current = remainingTime; clearInterval(timerRef.current); } }
如果修复后还是出现倒计时值不对的问题,检查下startTimer内部的倒计时逻辑,不要直接在定时器回调里读remainingTime state,容易碰到闭包陷阱拿到旧值,把剩余时间也改成ref存储即可。
内容的提问来源于stack exchange,提问作者user17075469
相关产品推荐
相关产品推荐

