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

如何在ReactJS中实时实现localStorage数据的增删改查?

实现localStorage数据实时渲染与UI同步

我需要制作一个从localStorage渲染数据的页面,要求删除localStorage中的数据时,对应UI内容能实时移除。目前遇到两个问题:

  • 代码片段1无法实现实时更新,必须刷新页面才能看到变化
  • 代码片段2虽能达到预期效果,但触发了maximum depth render(最大渲染深度)错误
    此外,组件中有编辑、删除按钮,希望操作单个数据时,对应内容能从localStorage中实时消失,无需刷新页面。

现有代码片段

代码片段1

const [favoritesPkg, setFavoritesPkg] = useState([]);

useEffect(() => {
    let a = JSON.parse(localStorage.getItem("savedPkg"));
    setFavoritesPkg(a);
}, []);

const handleRemoveAll = () => {
    localStorage.removeItem("savedPkg");
};

return (...)

代码片段2

const [favoritesPkg, setFavoritesPkg] = useState([]);
useEffect(() => {
    let a = JSON.parse(localStorage.getItem("savedPkg"));
    setFavoritesPkg(a);
}, [favoritesPkg]);

const handleRemoveAll = () => {
    localStorage.removeItem("savedPkg");
}

问题原因分析

  1. 代码片段1:useEffect的依赖数组为空,仅在组件挂载时执行一次读取localStorage的操作。后续localStorage数据变化时,组件不会重新读取数据,因此UI无法实时更新。
  2. 代码片段2:将favoritesPkg作为useEffect的依赖项,每次调用setFavoritesPkg更新状态后,useEffect会重新执行,再次读取localStorage并调用setFavoritesPkg,形成无限循环,触发最大渲染深度错误。

正确实现方案

1. 核心实现:同步localStorage与组件状态

通过封装统一的数据更新函数,结合storage事件监听,确保UI与localStorage实时同步:

import { useState, useEffect } from 'react';

const FavoritesComponent = () => {
  const [favoritesPkg, setFavoritesPkg] = useState([]);

  // 初始化加载数据+监听跨标签页storage变化
  useEffect(() => {
    const loadSavedData = () => {
      const rawData = localStorage.getItem("savedPkg");
      setFavoritesPkg(rawData ? JSON.parse(rawData) : []);
    };

    // 组件挂载时加载初始数据
    loadSavedData();
    // 监听其他标签页的localStorage修改事件
    window.addEventListener('storage', loadSavedData);

    // 组件卸载时移除监听
    return () => window.removeEventListener('storage', loadSavedData);
  }, []);

  // 统一更新localStorage和组件状态的函数
  const syncDataToLocalStorage = (newData) => {
    localStorage.setItem("savedPkg", JSON.stringify(newData));
    setFavoritesPkg(newData);
  };

  // 删除全部数据
  const handleRemoveAll = () => {
    syncDataToLocalStorage([]);
  };

  // 删除单个数据(假设每条数据有唯一id标识)
  const handleRemoveSingle = (itemId) => {
    const updatedData = favoritesPkg.filter(item => item.id !== itemId);
    syncDataToLocalStorage(updatedData);
  };

  // 编辑单个数据(传入修改后的完整数据项)
  const handleEditSingle = (updatedItem) => {
    const updatedData = favoritesPkg.map(item => 
      item.id === updatedItem.id ? updatedItem : item
    );
    syncDataToLocalStorage(updatedData);
  };

  return (
    <div className="favorites-container">
      <button onClick={handleRemoveAll} className="remove-all-btn">删除全部收藏</button>
      {favoritesPkg.map(item => (
        <div key={item.id} className="favorite-item">
          <h3>{item.name}</h3>
          <p>{item.description}</p>
          <button onClick={() => handleEditSingle({...item, name: `[编辑后]${item.name}`})}>编辑</button>
          <button onClick={() => handleRemoveSingle(item.id)}>删除</button>
        </div>
      ))}
    </div>
  );
};

export default FavoritesComponent;

2. 关键细节说明

  • 统一数据更新函数:syncDataToLocalStorage同时处理localStorage写入和组件状态更新,确保两者始终保持一致,避免状态与存储数据脱节。
  • 跨标签页同步:通过storage事件监听其他标签页对localStorage的修改,保证多标签场景下的数据同步。
  • 避免无限循环:useEffect仅在组件挂载时执行初始化和事件绑定,依赖数组为空,不会触发重复渲染循环。

内容的提问来源于stack exchange,提问作者fyz 08

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 20:23:34