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
相关产品推荐
相关产品推荐

