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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 00:35:24