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

React页面刷新后useEffect导致localStorage存储数据丢失问题排查

问题原因与解决方案

核心问题

你遇到的问题根源有两个:

  1. 初始state的副作用:你在useState里直接用nanoid()生成初始笔记ID,这意味着每次组件初始化(包括页面刷新)都会生成全新的初始笔记数组。而依赖notes的第二个useEffect会在组件首次渲染时就执行,把这个全新的初始数组写入localStorage,直接覆盖掉之前保存的数据。
  2. Strict Mode的放大效应:React开发环境默认开启Strict Mode,它会让组件初始化和useEffect执行两次。第一次挂载时,你的第一个useEffect读取到旧的保存数据并更新notes,但第二次挂载时,组件又会重新生成初始笔记数组,再次触发第二个useEffect覆盖localStorage,最终页面显示的就是硬编码的初始数据。

修复方案

最简洁靠谱的方式是把初始state的默认值直接从localStorage读取,去掉第一个useEffect,避免顺序冲突:

const [notes, setNotes] = useState(() => {
  // 初始化时优先读取localStorage,没有的话再用默认数据
  const savedNotes = localStorage.getItem('react-notes');
  if (savedNotes) {
    return JSON.parse(savedNotes);
  }
  // 只有localStorage为空时才生成默认笔记
  return [
    {
      noteId: nanoid(),
      text: 'This is my 1st note!',
      date: '30/07/2022'
    },
    {
      noteId: nanoid(),
      text: 'This is my 2nd note!',
      date: '30/07/2022'
    }
  ];
});

// 只保留这个useEffect,当notes变化时同步到localStorage
useEffect(() => {
  localStorage.setItem('react-notes', JSON.stringify(notes));
  console.log('saved notes:', notes);
}, [notes]);

为什么这样可行?

  • 用useState的函数式初始化,只会在组件首次挂载时执行一次,不会每次渲染都重新生成默认数组,也避免了和useEffect的执行顺序冲突。
  • 优先读取localStorage,确保页面刷新时直接加载保存的数据,而不是先显示初始数据再替换,解决了数据“消失”的问题。
  • 第二个useEffect只负责在notes变化时同步到localStorage,逻辑清晰,不会出现多余的触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:27:25