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

React中setInterval内结合useState使用if条件不生效如何解决

问题原因
  • 你的useEffect没有传入依赖数组,每次组件状态更新触发重渲染时都会重新执行,不断创建新的定时器,导致进度增长速度远超预期。
  • 定时器ID存储在普通局部变量progressTimer中,每次组件重渲染都会重置该变量,执行clearInterval时根本无法拿到之前创建的定时器ID,导致定时器无法被正常清除。
  • handleTime函数通过闭包捕获的progress值是初始化时的旧值,判断逻辑无法正确匹配最新的状态,也会导致清除逻辑失效。
修复方案

修改后的完整代码如下:

import { useState, useEffect, useRef } from "react";
import "./styles.css";

export default function App() {
  const [progress, setProgress] = useState(0);
  // 使用useRef存储定时器ID,跨渲染周期保持引用不变
  const progressTimerRef = useRef(null);

  function handleTime() {
    setProgress((prevState) => {
      if (prevState < 100) {
        return prevState + 10;
      } else {
        // 进度达到阈值后清除定时器
        clearInterval(progressTimerRef.current);
        return prevState;
      }
    });
  }

  function handlePlay() {
    progressTimerRef.current = setInterval(handleTime, 1000);
  }

  useEffect(() => {
    handlePlay();
    // 组件卸载时清除定时器,避免内存泄漏
    return () => clearInterval(progressTimerRef.current);
  }, []); // 空依赖数组,仅在组件挂载时执行一次,避免重复创建定时器

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      {progress}
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

核心修改点

  • 给useEffect添加空依赖数组,仅在组件首次挂载时启动一次定时器,避免重复创建
  • 用useRef存储定时器ID,保证所有渲染周期都可以访问到同一个定时器实例,清除操作可以正常生效
  • 把进度阈值判断放到setProgress的回调函数中,直接获取最新的状态值,规避闭包捕获旧状态的问题
  • 新增useEffect的清理回调,组件卸载时自动清除定时器,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 07:15:03