如何在React JS的useStopwatch Hook中实现LocalStorage计时持久化?
为秒表Hook实现LocalStorage持久化
问题
已完成秒表功能开发,但页面刷新或关闭后计时会从零重置,需要通过LocalStorage持久化计时数据,避免状态丢失。
解决方案
核心是持久化已流逝时间(elapsedTime)——所有时间计算都基于这个值。具体修改步骤如下:
- 将
elapsedTime从普通变量转为React状态,初始化时优先从LocalStorage读取历史数据 - 每次更新计时数据时,同步将
elapsedTime存入LocalStorage - 重置秒表时,清空LocalStorage中的对应数据
- 组件挂载时直接加载历史时间状态,无需等待用户手动启动
修改后的完整代码
"use client"; import { useState, useEffect } from "react"; const STORAGE_KEY = "stopwatch_elapsed_time"; export default function useStopwatch() { const [days, setDays] = useState(0); const [hrs, setHrs] = useState(0); const [mins, setMins] = useState(0); const [secs, setSecs] = useState(0); const [progressTime, setProgressTime] = useState(0); const [intervalId, setIntervalId] = useState<NodeJS.Timeout | undefined>(); // 从LocalStorage初始化已流逝时间,无数据则设为0 const [elapsedTime, setElapsedTime] = useState(() => { const saved = localStorage.getItem(STORAGE_KEY); return saved ? parseInt(saved, 10) : 0; }); let startTime = 0; // 组件挂载时,根据保存的elapsedTime初始化时间显示 useEffect(() => { if (elapsedTime > 0) { const secs = Math.floor((elapsedTime / 1000) % 60); const mins = Math.floor((elapsedTime / (1000 * 60)) % 60); const hrs = Math.floor((elapsedTime / (1000 * 60 * 60)) % 60); const days = Math.floor(elapsedTime / (1000 * 60 * 60 * 24)); setDays(days); setHrs(hrs); setMins(mins); setSecs(secs); setProgressTime(elapsedTime); } }, []); const start = () => { startTime = Date.now() - elapsedTime; const id = setInterval(updateTime, 1000); setIntervalId(id); }; const restart = () => { clearInterval(intervalId); // 重置所有状态 setDays(0); setHrs(0); setMins(0); setSecs(0); setElapsedTime(0); setProgressTime(0); startTime = 0; // 清空LocalStorage中的计时数据 localStorage.removeItem(STORAGE_KEY); start(); }; const updateTime = () => { const newElapsedTime = Date.now() - startTime; // 更新状态 setElapsedTime(newElapsedTime); // 同步存储到LocalStorage localStorage.setItem(STORAGE_KEY, newElapsedTime.toString()); const secs = Math.floor((newElapsedTime / 1000) % 60); const mins = Math.floor((newElapsedTime / (1000 * 60)) % 60); const hrs = Math.floor((newElapsedTime / (1000 * 60 * 60)) % 60); const days = Math.floor(newElapsedTime / (1000 * 60 * 60 * 24)); setDays(days); setHrs(hrs); setMins(mins); setSecs(secs); setProgressTime(newElapsedTime); }; return { days, hrs, mins, secs, progressTime, start, restart }; }
关键说明
- 统一存储键名:用
STORAGE_KEY避免硬编码出错,方便后续维护 - 函数式初始化状态:确保只在组件挂载时读取一次LocalStorage,避免重复操作
- 挂载时加载历史数据:页面刷新后直接显示之前的计时状态,提升用户体验
- 实时同步存储:每次计时更新都将最新的
elapsedTime存入LocalStorage,保证数据一致性 - 重置时清空存储:避免残留数据影响下一次计时
内容的提问来源于stack exchange,提问作者Rakibul
相关产品推荐
相关产品推荐

