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

React中如何实现点击按钮启动番茄钟计时器 支持暂停停止功能

核心问题分析
  • 原有代码没有设置计时器运行状态的控制变量,useEffect依赖seconds触发,页面加载后就会自动执行计时逻辑,无法手动控制启停
  • 把计时逻辑封装到点击事件后只执行一次,是因为单次点击仅触发一次函数调用,没有设置持续运行的定时器,也没有和状态联动实现重复执行
  • 原有代码中每次执行interval就主动清除定时器,且没有统一的定时器清理逻辑,存在逻辑错误和内存泄漏风险
可直接运行的修正代码
import React, { useEffect, useState, useRef } from "react";

function App() {
  const [minutes, setMinutes] = useState(25);
  const [seconds, setSeconds] = useState(0);
  const [displayMessage, setDisplayMessage] = useState(false);
  // 控制计时器是否运行的状态
  const [isRunning, setIsRunning] = useState(false);
  // 存储定时器ID,方便全局清理
  const intervalRef = useRef(null);

  // 统一的定时器清理方法
  const clearTimer = () => {
    if (intervalRef.current) {
      clearInterval(intervalRef.current);
      intervalRef.current = null;
    }
  };

  useEffect(() => {
    // 非运行状态直接返回,不启动计时器
    if (!isRunning) return;

    intervalRef.current = setInterval(() => {
      if (seconds === 0) {
        if (minutes !== 0) {
          setSeconds(59);
          setMinutes(minutes - 1);
        } else {
          const newMinutes = displayMessage ? 24 : 4;
          setSeconds(59);
          setMinutes(newMinutes);
          setDisplayMessage(!displayMessage);
        }
      } else {
        setSeconds(seconds - 1);
      }
    }, 1000);

    // 依赖变化/组件卸载时自动清理定时器
    return clearTimer;
  }, [isRunning, seconds, minutes, displayMessage]);

  // 启动按钮逻辑
  const handleStart = () => {
    setIsRunning(true);
  };

  // 暂停按钮逻辑
  const handlePause = () => {
    setIsRunning(false);
  };

  // 停止按钮逻辑
  const handleStop = () => {
    setIsRunning(false);
    clearTimer();
    // 重置为初始状态
    setMinutes(25);
    setSeconds(0);
    setDisplayMessage(false);
  };

  const timerMinutes = minutes < 10 ? `0${minutes}` : minutes;
  const timerSeconds = seconds < 10 ? `0${seconds}` : seconds;

  return (
    <div className="timer">
      <h2>
        {timerMinutes}:{timerSeconds}
      </h2>
      <button className="buttons_new" onClick={handleStart}>Start</button>
      <button className="buttons_new" onClick={handlePause}>Pause</button>
      <button className="buttons_new" onClick={handleStop}>Stop</button>
    </div>
  );
}

export default App;
关键改动说明
  • 新增isRunning状态变量,作为计时器是否启动的唯一开关
  • 新增intervalRef用useRef存储定时器ID,任意位置都可以调用清理方法终止计时器
  • 调整useEffect触发逻辑:仅当isRunning为true时才启动定时器,同时新增了统一的定时器清理逻辑,避免内存泄漏
  • 给三个按钮分别绑定对应的状态操作逻辑,实现点击启动、暂停、重置的需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 14:54:03