React函数仅读取初始状态求助:定时器无法识别状态更新
React定时器无法读取最新state的解决方案
问题原因
你遇到的是典型的React闭包陷阱:startTimer执行时,定时器的回调函数捕获了当时的update状态值(初始为0)。后续通过setUpdate更新state时,组件会重新渲染,但定时器回调属于旧渲染周期的闭包,里面的update永远是初始的0,因此update>9的判断永远不会触发,定时器无法停止。
解决方法:用useRef跟踪最新状态
useRef的.current属性是可变的,且不会随组件重新渲染重置,能始终拿到最新的状态值,完美解决闭包问题。
步骤1:创建ref同步state
const [update, setUpdate] = React.useState(0); // 创建ref保存最新的update值 const updateRef = React.useRef(update); // 每当update变化时,同步更新ref的current值 React.useEffect(() => { updateRef.current = update; }, [update]);
步骤2:修改定时器回调读取ref值
const startTimer = () => { let value = 0; const timerI = setInterval(function(){ value = value + 1/60; // 读取ref中保存的最新update值 if(updateRef.current > 9){ setResultGame(value.toFixed(2)); if(value < record){ setRecord(value); } clearInterval(timerI); } }, 1000/60); }
额外优化:函数式更新state
为避免verifingSpell中也出现闭包问题,建议使用函数式更新获取最新的state值:
const verifingSpell = (spell) => { if(spell === randomSpell){ generateSpell(); // 用函数式更新,确保拿到最新的update值 setUpdate(prevUpdate => prevUpdate + 1); console.log(spell, arr); } }
内容的提问来源于stack exchange,提问作者Ilia
相关产品推荐
相关产品推荐

