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

使用window.setInterval、useEffect和useState更新值失败求助

React计时器中modelResult始终为0的修复方案

我正在模拟一个依赖计时器值的模型结果计时器,期望每秒更新计时器的同时更新模型值。相关代码如下:

"use client";

import { useState, useEffect, useRef } from "react";

function calculateDuration(startTimestamp) {
  const currentDate = new Date();
  const timestamp = currentDate.getTime();
  const duration = timestamp - startTimestamp;
  return Math.round(duration / 1000);
}

function calculateModelResult(duration) {
  return duration * 0.1;
}

export default function Page() {
  const startTime = 1692699200000;
  const [duration, setDuration] = useState(0);
  const [modelResult, setModelResult] = useState(0);
  const testTimeRef = useRef(0);

  useEffect(() => {
    testTimeRef.current = window.setInterval(() => {
      setDuration(calculateDuration(startTime));
      setModelResult(calculateModelResult(duration));
    }, 1000);
  }, []);

  return (
    <h1>
      Hello, the duration is {duration}, the model result based on the current
      time is {modelResult}
    </h1>
  );
}

但运行后发现,duration能正常更新,modelResult却始终保持为0,运行效果如下:

Hello, the duration is 80188, the model result based on the current time is 0
Hello, the duration is 80196, the model result based on the current time is 0

问题原因

问题出在闭包捕获的状态值陈旧。useEffect的依赖数组为空,只会在组件挂载时执行一次,里面的定时器回调捕获的是初始的duration值(0),之后每次调用setModelResult时,都是基于这个初始值计算,结果自然一直是0。

修复方案

方案一:直接使用最新计算的duration值

在定时器回调里先计算出当前最新的duration,再用这个值同时更新两个状态,避开闭包的问题:

useEffect(() => {
  testTimeRef.current = window.setInterval(() => {
    const currentDuration = calculateDuration(startTime);
    setDuration(currentDuration);
    setModelResult(calculateModelResult(currentDuration));
  }, 1000);

  // 组件卸载时清理定时器,避免内存泄漏
  return () => clearInterval(testTimeRef.current);
}, []);

方案二:监听duration变化同步更新modelResult

单独加一个依赖duration的useEffect,当duration更新时自动计算并更新modelResult:

useEffect(() => {
  testTimeRef.current = window.setInterval(() => {
    setDuration(calculateDuration(startTime));
  }, 1000);

  return () => clearInterval(testTimeRef.current);
}, []);

// 当duration更新时,自动计算并更新modelResult
useEffect(() => {
  setModelResult(calculateModelResult(duration));
}, [duration]);

这两种方案都能解决问题,方案一更直接,方案二更符合React状态更新的逻辑,可根据实际场景选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 22:36:35