React实现长按按钮实时计时遇state更新无限循环问题求助
解决React长按按钮实时计数时的无限循环问题
你的问题核心在于组件重新渲染时普通变量会被重置,加上定时器创建逻辑的疏漏,导致每次调用setMs触发组件重渲染后,又会重新执行相关逻辑,最终引发无限循环。我来给你一步步修复:
问题分析
原代码里的counter和timerinterval是组件内的普通变量,每次组件因setMs更新状态而重新渲染时,这两个变量都会被重新初始化(let counter = 0; let timerinterval;)。同时setInterval的第二个参数你写成了数组[1000],这是错误的,而且timer函数里的条件判断逻辑也容易导致重复创建定时器,进一步加剧循环问题。
修复后的代码
import React, { useState, useEffect, useRef } from "react"; const Emergency = () => { const [ms, setMs] = useState(0); // 用useRef保存定时器和计数器,避免组件重渲染时被重置 const timerRef = useRef(null); const counterRef = useRef(0); const startTimer = () => { // 先清除可能存在的旧定时器,防止重复创建 if (timerRef.current) clearInterval(timerRef.current); counterRef.current = 1; setMs(counterRef.current); timerRef.current = setInterval(() => { counterRef.current += 1; setMs(counterRef.current); }, 1000); }; const stopTimer = () => { if (timerRef.current) { clearInterval(timerRef.current); timerRef.current = null; } counterRef.current = 0; setMs(0); }; const pressingDown = (e) => { e.preventDefault(); startTimer(); }; const notPressingDown = (e) => { e.preventDefault(); stopTimer(); }; // 组件卸载时清理定时器,防止内存泄漏 useEffect(() => { return () => { if (timerRef.current) clearInterval(timerRef.current); }; }, []); return ( <> <button onMouseDown={pressingDown} onMouseUp={notPressingDown} onTouchStart={pressingDown} onTouchEnd={notPressingDown} className="button is-primary mt-3" > Emergency </button> <br /> Time holding it is.... {ms} </> ); }; export default Emergency;
关键修改点
- 用
useRef存储定时器和计数器:useRef的.current属性在组件整个生命周期内保持不变,不会因组件重渲染而重置,完美解决了原代码中变量被重复初始化的问题。 - 完善定时器创建/清理逻辑:每次启动定时器前先清除旧的,避免多个定时器同时运行;停止时彻底清空定时器引用,防止内存泄漏。
- 修正
setInterval参数:把错误的数组[1000]改成正确的毫秒数1000。 - 添加组件卸载时的清理:通过
useEffect的返回函数,在组件被卸载时自动清除定时器,避免潜在的内存泄漏问题。
这样修改后,长按按钮时会实时更新秒数,松开后重置为0,而且不会再出现无限循环的问题,完全满足你的用户体验需求。
内容的提问来源于stack exchange,提问作者Ronald Langeveld
相关产品推荐
相关产品推荐

