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

React中setInterval始终使用useState默认值的问题排查

React中setInterval无法获取最新state的原因及解决方法

问题原因

你的useEffect依赖数组为空,这意味着它只会在组件首次渲染时执行一次。setInterval的回调函数形成了闭包,捕获的是组件首次渲染时所有state变量的初始值(比如FilterType默认是3)。后续用户操作修改state时,组件会重新渲染,但这个旧的interval回调不会被更新,依然持有首次渲染时的state值,所以API调用永远用的是默认值。

解决方案

方法一:将用到的state变量加入useEffect依赖数组

每当依赖的state变量变化时,useEffect会重新执行,清除旧的interval并创建新的interval,新的回调就能捕获到最新的state值。

修改后的代码:

useEffect(() => {
    const interval = setInterval(() => {
        if (FilterType === 1){
            LoadAnnualStats(Year)
        } else if (FilterType === 2){
            LoadMonthlyStats(`${MonthYear}-${Month}`)
        } else if (FilterType === 3){
            LoadDayStats(CurrentDate)
        } else if (FilterType === 4){
            LoadCustomStats(FromDate, ToDate)
        } else if (FilterType === 5){
            LoadDayStats(yesterday)
        }
    }, 10000)
    return () => clearInterval(interval);
}, [FilterType, Year, MonthYear, Month, CurrentDate, FromDate, ToDate, yesterday])

注意要把所有在回调中用到的变量都加入依赖数组,包括yesterday(如果它是动态变化的)。

方法二:用useRef保存最新state引用

创建useRef对象同步最新的state值,让interval回调通过ref的current属性访问最新值,避免频繁销毁重建interval。

步骤如下:

  1. 创建对应state的ref对象
  2. 同步state变化到ref
  3. 在interval回调中使用ref.current获取最新值

代码示例:

// 1. 创建ref对象
const filterRef = useRef(FilterType);
const yearRef = useRef(Year);
const monthYearRef = useRef(MonthYear);
const monthRef = useRef(Month);
const currentDateRef = useRef(CurrentDate);
const fromDateRef = useRef(FromDate);
const toDateRef = useRef(ToDate);

// 2. 同步state到ref
useEffect(() => {
    filterRef.current = FilterType;
    yearRef.current = Year;
    monthYearRef.current = MonthYear;
    monthRef.current = Month;
    currentDateRef.current = CurrentDate;
    fromDateRef.current = FromDate;
    toDateRef.current = ToDate;
}, [FilterType, Year, MonthYear, Month, CurrentDate, FromDate, ToDate])

// 3. interval中使用ref.current
useEffect(() => {
    const interval = setInterval(() => {
        const currentFilter = filterRef.current;
        if (currentFilter === 1){
            LoadAnnualStats(yearRef.current)
        } else if (currentFilter === 2){
            LoadMonthlyStats(`${monthYearRef.current}-${monthRef.current}`)
        } else if (currentFilter === 3){
            LoadDayStats(currentDateRef.current)
        } else if (currentFilter === 4){
            LoadCustomStats(fromDateRef.current, toDateRef.current)
        } else if (currentFilter === 5){
            LoadDayStats(yesterday)
        }
    }, 10000)
    return () => clearInterval(interval);
}, [yesterday])

这种方法适合state变化频繁的场景,避免了每次state变化都重建interval的开销。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 16:52:40