页面刷新后localStorage未保存数据?React状态重置为空数组问题
问题:刷新网站后state重置为空数组
刷新网站后,history状态会重置为空数组。已通过console.log调试确认:history能正常保存到localStorage,也能正常从localStorage读取,但读取后history似乎被重新设置为空数组。
原代码:
import { useState, useRef, useEffect } from 'react' import './styles.css' import History from './History' const LOCALSTORAGEKEY = './finance/src/app/12321'; function App() { const [history, setHistory] = useState([]); const amnt = useRef(); const item = useRef(); useEffect(()=>{ const stor = JSON.parse(localStorage.getItem(LOCALSTORAGEKEY)); if (stor) setHistory(stor) },[]) useEffect(()=>{ if(history){ console.log(JSON.stringify(history)) localStorage.setItem(LOCALSTORAGEKEY,JSON.stringify(history)) } },[history]) const now = new Date(); const handleNewamnt = () =>{ setHistory(prev=>{ return([...prev, {'id':item.current.value ,'item': item.current.value, 'amnt': amnt.current.value, 'date': JSON.stringify(now) }]); }) item.current.value = '' amnt.current.value = '' }; return ( <> <History history_object= {history}/> <input placeholder='amount' type='number' ref={amnt} /> <input placeholder='item' type='text' ref={item} /> <button onClick={handleNewamnt}>confirm </button> </> ) } export default App
解决方案
问题原因
useEffect执行顺序冲突:组件挂载时,依赖history的第二个useEffect会先于第一个useEffect的状态更新生效,把初始的空数组[]存入localStorage,覆盖了原本存储的有效数据。- 状态初始化时机滞后:原本通过
useEffect在组件挂载后读取localStorage设置状态,导致组件初始渲染时状态是空数组,后续才更新,期间可能触发不必要的存储操作。
修改后的代码
import { useState, useRef, useEffect } from 'react' import './styles.css' import History from './History' // 简化localStorage的key命名,避免特殊字符问题 const LOCALSTORAGEKEY = 'finance-history'; function App() { // 直接在useState初始化时从localStorage读取数据,避免异步更新的问题 const [history, setHistory] = useState(() => { const storedData = localStorage.getItem(LOCALSTORAGEKEY); return storedData ? JSON.parse(storedData) : []; }); const amnt = useRef(); const item = useRef(); // 仅在history变化时保存到localStorage,无需多余判断 useEffect(()=>{ localStorage.setItem(LOCALSTORAGEKEY, JSON.stringify(history)); },[history]) const handleNewamnt = () =>{ // 点击时才生成当前时间,避免组件初始化时时间固定 const now = new Date(); setHistory(prev=>{ return([...prev, {'id': item.current.value ,'item': item.current.value, 'amnt': amnt.current.value, 'date': JSON.stringify(now) }]); }) item.current.value = '' amnt.current.value = '' }; return ( <> <History history_object= {history}/> <input placeholder='amount' type='number' ref={amnt} /> <input placeholder='item' type='text' ref={item} /> <button onClick={handleNewamnt}>confirm </button> </> ) } export default App
关键修改点
- 状态初始化优化:将
localStorage的读取逻辑移到useState的初始化函数中,组件挂载时直接获取正确的初始状态,避免异步更新导致的状态滞后。 - 简化
localStorage键名:替换带有路径的复杂键名,避免潜在的存储键名冲突或解析问题。 - 修复时间生成逻辑:将
now = new Date()移到handleNewamnt函数内部,确保每次点击按钮时生成的是当前时间,而不是组件初始化时的固定时间。 - 移除无效判断:第二个
useEffect中的if(history)判断无意义(空数组在JS中是真值),直接保存状态即可。
内容的提问来源于stack exchange,提问作者Trevor Clute
相关产品推荐
相关产品推荐

