React番茄钟应用切换标签后,如何持续更新页面标题?
解决React番茄钟后台标签标题跳变问题
核心思路
放弃依赖setInterval每秒更新状态的方式,改用记录起始时间戳+实时计算耗时的方案。浏览器后台节流的是定时器,但系统时间会持续推进,通过时间差计算能得到准确耗时,避免标题跳变。
具体实现步骤
- 存储起始时间戳:工作模式启动时,将当前时间戳(
Date.now())存入状态,同时标记工作状态(isWorking)。 - 替换定时器逻辑:用
setInterval或requestAnimationFrame触发更新,但每次更新都通过当前时间与起始时间的差值计算真实耗时,而非依赖累计的每秒状态更新。 - 绑定计算后的耗时到标题:通过React Helmet直接绑定计算出的分秒格式耗时,确保切回标签时显示准确值。
代码示例
import { useState, useEffect, useRef } from 'react'; import { Helmet } from 'react-helmet'; const PomodoroTimer = () => { const [isWorking, setIsWorking] = useState(false); const [startTime, setStartTime] = useState(null); const [elapsedTime, setElapsedTime] = useState(0); const timerRef = useRef(null); // 格式化毫秒为mm:ss格式 const formatTime = (ms) => { const totalSeconds = Math.floor(ms / 1000); const minutes = String(Math.floor(totalSeconds / 60)).padStart(2, '0'); const seconds = String(totalSeconds % 60).padStart(2, '0'); return `${minutes}:${seconds}`; }; useEffect(() => { if (isWorking) { // 启动时记录起始时间 setStartTime(Date.now()); // 定时器每秒触发,但每次都计算真实时间差 timerRef.current = setInterval(() => { const currentElapsed = Date.now() - startTime; setElapsedTime(currentElapsed); }, 1000); } else { clearInterval(timerRef.current); } return () => clearInterval(timerRef.current); }, [isWorking, startTime]); return ( <> <Helmet> <title>{isWorking ? `Work - ${formatTime(elapsedTime)}` : '番茄钟'}</title> </Helmet> <button onClick={() => setIsWorking(!isWorking)}> {isWorking ? '停止工作' : '开始工作'} </button> </> ); }; export default PomodoroTimer;
进阶优化
如果想让切回标签时的更新更及时,可以用requestAnimationFrame替代setInterval,它在标签激活后会立即触发更新:
useEffect(() => { if (isWorking) { setStartTime(Date.now()); const updateElapsed = () => { const currentElapsed = Date.now() - startTime; setElapsedTime(currentElapsed); timerRef.current = requestAnimationFrame(updateElapsed); }; timerRef.current = requestAnimationFrame(updateElapsed); } else { cancelAnimationFrame(timerRef.current); } return () => cancelAnimationFrame(timerRef.current); }, [isWorking, startTime]);
这种方案的核心是不依赖定时器的累计更新,每次都基于系统时间计算真实耗时,无论浏览器是否节流定时器,切回标签时都能直接显示正确的耗时,和谷歌秒表的实现逻辑一致。
内容的提问来源于stack exchange,提问作者Ammar Ahmed
相关产品推荐
相关产品推荐

