React严格模式下LocalStorage数据刷新重置问题排查
问题原因
React严格模式在开发环境下会刻意重复执行组件的挂载/卸载流程,包括副作用函数(useEffect),这直接导致了你的localStorage数据被意外覆盖。
结合你的代码,严格模式下的执行顺序是这样的:
- 第一次组件挂载:
- 第一个
useEffect从localStorage读取数据并更新到store - 第二个
useEffect触发,把store里的正确数据存回localStorage
- 第一个
- 严格模式强制卸载组件后重新挂载:
- store回到初始值(比如空数组)
- 第二个
useEffect因notes从正确值变回初始值而触发,把初始值写入localStorage,直接覆盖了之前的有效数据 - 重新挂载的第一个
useEffect读取到的已经是被覆盖的初始值,最终导致页面刷新后数据重置
解决方法
方法一:把数据读写逻辑移到状态管理中(推荐)
如果你的状态管理用的是Zustand(从useAppStore的调用方式推测),可以直接在store初始化时读取localStorage,更新时同步写入,彻底避免组件副作用的干扰:
const useAppStore = create((set) => ({ // 初始化时直接加载localStorage数据 notes: JSON.parse(localStorage.getItem("react-todoList") || "[]"), setNotes: (newNotes) => { set({ notes: newNotes }); // 更新时同步写入localStorage localStorage.setItem("react-todoList", JSON.stringify(newNotes)); }, }));
之后组件里的两个useEffect都可以删掉,不管严格模式如何执行,store都会优先读取localStorage的有效数据,不会出现重置问题。
方法二:给组件副作用加判断逻辑
如果不想修改store,可以在第二个useEffect里增加判断,避免把初始值写入localStorage:
useEffect(() => { const storedNotes = JSON.parse(localStorage.getItem("react-todoList") || "[]"); // 仅当当前notes和localStorage数据不一致时才写入 if (JSON.stringify(notes) !== JSON.stringify(storedNotes)) { localStorage.setItem("react-todoList", JSON.stringify(notes)); } }, [notes]);
这样即使严格模式重复挂载组件,初始值也不会覆盖localStorage里的有效数据,第一个useEffect读取的始终是正确内容。
内容的提问来源于stack exchange,提问作者Muaz zia
相关产品推荐
相关产品推荐

