You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么React中setInterval触发useState递增时,打印值始终为0?

问题原因分析

核心原因是React函数组件的闭包捕获特性,具体逻辑如下:

  • 你的useEffect依赖项是空数组,所以这个副作用只会在组件首次挂载时执行1次,后续组件重渲染都不会再运行。
  • 首次渲染时,inc的初始值是0,定时器的回调函数在这一刻被创建,闭包捕获了当前作用域下的inc = 0这个值。
  • 你调用setInc时用了函数式更新写法prevState => prevState +1,这个更新逻辑是从React内部维护的最新状态快照取值计算,所以状态inc本身是能正常递增的,只是定时器回调始终拿着首次渲染时捕获的旧inc值,所以每次打印都是0。
两种常用解决方案

方案1:将inc加入useEffect依赖数组

把inc加入依赖后,每次inc变化都会重新执行副作用:销毁旧定时器、创建新定时器,新的定时器回调会捕获到最新的inc值,打印结果就正常了。

const [inc, setInc] = useState(0);
useEffect(() => {
    const ti = setInterval(() => {
        setInc(prevState => prevState + 1);
        console.log(inc);
    }, 3000)
    return () => {
        clearInterval(ti);
    }
}, [inc]);

方案2:用useRef存储最新状态

如果不想频繁销毁重建定时器,可以用useRef来同步最新的inc值,ref的current属性是可变的,不会被闭包捕获限制:

const [inc, setInc] = useState(0);
const incRef = useRef(inc);
// 同步最新的inc到ref
useEffect(() => {
  incRef.current = inc;
}, [inc]);

useEffect(() => {
    const ti = setInterval(() => {
        setInc(prevState => prevState + 1);
        console.log(incRef.current);
    }, 3000)
    return () => {
        clearInterval(ti);
    }
}, []);

内容的提问来源于stack exchange,提问作者Paj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 04:15:08