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

页面重载后localStorage存储的数据丢失问题求助

问题分析

你的代码存在关键逻辑冲突:

  • 组件挂载时,第一个useEffect尝试从localStorage读取数据更新contacts状态,但这个更新是异步的;
  • 同时第二个useEffect因依赖contacts,会在组件挂载(此时contacts初始值为空数组)时立刻执行,把空数组写入localStorage,直接覆盖之前存储的有效数据——这就是刷新后数据丢失的核心原因。
修复方案

方案1:初始化状态时直接读取localStorage(推荐)

将useState的初始值改为从localStorage读取,同时优化状态更新逻辑避免闭包问题:

import "./App.css";

import React, { useState, useEffect } from "react";
import Header from "../components/Header";
import AddContact from "../components/AddContact";
import ContactList from "../components/ContactList";

function App() {
  const LOCAL_STORAGE_KEY = "contacts";
  // 初始化时直接从localStorage读取数据,避免异步竞态
  const [contacts, setContacts] = useState(() => {
    const savedContacts = localStorage.getItem(LOCAL_STORAGE_KEY);
    return savedContacts ? JSON.parse(savedContacts) : [];
  });

  // 用函数式更新,避免闭包捕获旧状态导致的更新错误
  const addContactHandler = (contact) => {
    setContacts(prevContacts => [...prevContacts, contact]);
  };

  // 仅在contacts变化时写入localStorage,此时初始值已从localStorage读取,不会覆盖有效数据
  useEffect(() => {
    localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(contacts));
  }, [contacts]);

  return (
    <div className="ui container">
      <Header />
      <AddContact addContactHandler={addContactHandler} />
      <ContactList contacts={contacts} />
    </div>
  );
}

export default App;

方案2:修改第二个useEffect的触发条件

如果不想调整初始化逻辑,可以给第二个useEffect添加判断,避免初始空数组覆盖数据:

// 替换原第二个useEffect
useEffect(() => {
  // 仅当contacts非空时执行存储,避免初始空数组覆盖原有数据
  if (contacts.length > 0) {
    localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(contacts));
  }
}, [contacts]);
额外说明
  • 使用函数式更新(setContacts(prev => ...))能避免闭包捕获旧状态导致的更新错误,在多次添加联系人时更可靠;
  • 初始化时直接读取localStorage是React官方推荐的方式,比用useEffect读取更高效,也能彻底规避异步更新带来的竞态问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 01:02:22