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

React应用中setInterval失效:倒计时时器无法正常运行

问题原因分析
  1. 定时器引用丢失:timerInt是组件内的普通变量,组件每次状态更新重新渲染时,该变量会被重置,导致无法持续控制定时器。
  2. 闭包捕获旧状态:timerF函数读取的sec和min是组件首次渲染时的闭包值,不会随状态更新同步,后续判断逻辑一直基于旧值执行,导致倒计时失效。
  3. 状态更新顺序错误:无论什么情况最后都执行setSec(prev=>prev-1),会覆盖sec===0时设置的setSec(59),逻辑冲突。
  4. 初始化逻辑遗漏:点击开始按钮后未将秒数初始化为59,不符合需求。
修复后的代码
import { useState, useRef, useEffect } from 'react';

function CountdownTimer() {
  const [min, setMin] = useState(10);
  const [sec, setSec] = useState(0);
  const [disabledBtn, setDisabledBtn] = useState(false);
  // 用useRef保存定时器引用,避免组件重渲染丢失
  const timerInt = useRef(null);

  const timer = () => {
    // 清除已有定时器,防止重复点击创建多个实例
    if (timerInt.current) clearInterval(timerInt.current);
    
    timerInt.current = setInterval(() => {
      setMin(prevMin => {
        return setSec(prevSec => {
          // 判断倒计时是否结束
          if (prevSec <= 0 && prevMin <= 0) {
            clearInterval(timerInt.current);
            setDisabledBtn(false);
            return 0;
          }
          // 秒数为0时重置为59,触发分钟减1
          if (prevSec === 0) {
            return 59;
          }
          // 正常秒数递减
          return prevSec - 1;
        }) || (prevSec === 0 && prevMin > 0 ? prevMin - 1 : prevMin);
      });
    }, 1000);
  };

  const handleStart = (time) => {
    // 初始化分钟和秒数,符合点击开始后秒数为59的需求
    setMin(time);
    setSec(59);
    setDisabledBtn(true);
    timer();
  };

  // 组件卸载时清除定时器,防止内存泄漏
  useEffect(() => {
    return () => {
      if (timerInt.current) clearInterval(timerInt.current);
    };
  }, []);

  return (
    <div>
      <div className="time">
        <div className="time-min">{min}</div>
        <span>:</span>
        <div className="time-sec">{sec < 10 ? `0${sec}` : sec}</div>
      </div>
      <button
        className="start-btn active-btn"
        type="button"
        disabled={disabledBtn}
        onClick={() => handleStart(10)}
      >
        START
      </button>
    </div>
  );
}

export default CountdownTimer;
关键修复点说明
  • 用useRef存储定时器引用,确保组件重渲染时不丢失对定时器的控制。
  • 采用状态的函数式更新,确保每次状态修改都基于最新值。
  • 调整逻辑顺序,先判断倒计时是否结束,再处理秒数和分钟的更新,避免状态覆盖。
  • 点击开始按钮时直接初始化秒数为59,匹配需求。
  • 添加组件卸载时的定时器清理逻辑,防止内存泄漏。
  • 优化按钮disabled属性写法,直接使用布尔值即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 11:02:58