React Hook state值在周期触发的函数中未更新该如何解决?
问题根因
这是典型的React Hooks闭包陷阱:
- 组件首次渲染时,
triggeredEveryFiveSeconds函数会捕获当前渲染上下文的check初始值true - 后续调用
setCheck更新状态只会触发组件重渲染、生成新的triggeredEveryFiveSeconds函数实例,但已经启动的定时器绑定的还是首次渲染的旧函数,始终引用初始check值,无法同步最新状态。
解决方案
方案1:用useRef同步状态(推荐,不改变定时器间隔)
用useRef存储状态的最新快照,所有渲染上下文共享同一个ref引用,定时器直接读取ref的current属性即可拿到最新值:
const [check, setCheck] = useState(true); // 新增ref同步check的最新值 const checkRef = useRef(check); // check更新时同步到ref useEffect(() => { checkRef.current = check; console.log("useEffect Check value: " + check); }, [check]); const buttonToToggleCheckValue = () => { console.log("Toggle check"); setCheck(!check); }; // Call this function every 5 seconds const triggeredEveryFiveSeconds = () => { // 读取ref的最新值 console.log("Check value: " + checkRef.current); };
该方案无需重启定时器,不会打乱原有的5秒触发节奏,适合大部分场景。
方案2:将状态加入定时器依赖,状态更新时重启定时器
把定时器启动逻辑封装到useEffect中,将check加入依赖数组,状态变更时自动销毁旧定时器、启动绑定了最新状态的新定时器:
useEffect(() => { // 启动定时器,绑定当前渲染上下文的最新check值 const timer = setInterval(triggeredEveryFiveSeconds, 5000); // 依赖变更/组件卸载时清除旧定时器 return () => clearInterval(timer); }, [check]);
注意:该方案每次check更新都会重置定时器计时,如果你需要严格的固定5秒间隔(不受状态更新影响)不推荐使用。
内容的提问来源于stack exchange,提问作者Ng Zen
相关产品推荐
相关产品推荐

