每次刷新后React localStorage值都会重置

问题描述 投票:0回答:3
每当将新项目添加到列表中时,本地存储都会更新,但是如果我刷新页面。键保留,但值重置为空数组。

import { useState, useEffect } from 'react'; function App() { const [data, setData] = useState([]); const [input, setInput] = useState(''); useEffect(() => { const storedData = localStorage.getItem('react-data-store'); if (storedData) { setData(JSON.parse(storedData)); } }, []); useEffect(() => { localStorage.setItem('react-data-store', JSON.stringify(data)); }, [data]); const handleAddItem = () => { if (input) { const newItem = { id: crypto.randomUUID(), text: input }; setData([...data, newItem]); setInput(''); } }; return ( <> <input type='text' value={input} onChange={(e) => setInput(e.target.value)} /> <button onClick={handleAddItem}>Add Item</button> <ul> {data.map((item) => ( <li key={item.id}>{item.text}</li> ))} </ul> </> ); } export default App;
我期望即使刷新后列表也会保留,但数据不会保留。

javascript reactjs react-hooks local-storage
3个回答
0
投票
这两个 useEffect 钩子相互冲突

useEffect(() => { const storedData = localStorage.getItem('react-data-store'); if (storedData) { setData(JSON.parse(storedData)); } }, []); useEffect(() => { localStorage.setItem('react-data-store', JSON.stringify(data)); }, [data]);
我的解决方案是创建一个新标志来检查数据是否从本地存储加载

const [isInit, setIsInit] = useState(false); useEffect(() => { const storedData = localStorage.getItem('react-data-store'); if (storedData) { setData(JSON.parse(storedData)); } setIsInit(true) }, []); useEffect(() => { if (isInit) localStorage.setItem('react-data-store', JSON.stringify(data)); }, [data, isInit]);
    

0
投票
每次刷新后 localStorage 值都会重置

setData

 是异步的。 
localStorage.setItem
 不是。第二个 
useEffect
 中的函数将在第一个 
setData
 中的 
useEffect
 之前调用,导致您的 
localStorage
 被空数组覆盖,因为在那一刻 
data
[]

useEffect(() => { const storedData = localStorage.getItem('react-data-store'); if (storedData) { setData(JSON.parse(storedData)); // will be called after second useEffect } }, []);
由于 

localStorage.setItem

 是同步的,我建议您完全删除第一个 
useEffect
 并将逻辑直接移至 
useState
 挂钩,使其成为 
default 值。

const [data, setData] = useState(() => { const storedData = localStorage.getItem('react-data-store'); if (storedData) { return JSON.parse(storedData); } return []; });
    

0
投票
检查 data 变量中是否有数据,因为监视数据的 useEffect 是在第一次渲染时调用的。

stakblitz 示例:

https://stackblitz.com/edit/react-bhdhmy?file=src%2FApp.js

import { useState, useEffect } from 'react'; function App() { const [data, setData] = useState([]); const [input, setInput] = useState(''); useEffect(() => { const storedData = localStorage.getItem('react-data-store'); if (storedData) { setData(JSON.parse(storedData)); } }, []); useEffect(() => { if (data.length > 0) // <----- here localStorage.setItem('react-data-store', JSON.stringify(data)); }, [data]); const handleAddItem = () => { if (input) { const newItem = { id: crypto.randomUUID(), text: input }; setData([...data, newItem]); setInput(''); } }; return ( <> <input type="text" value={input} onChange={(e) => setInput(e.target.value)} /> <button onClick={handleAddItem}>Add Item</button> <ul> {data.map((item) => ( <li key={item.id}>{item.text}</li> ))} </ul> </> ); } export default App;
    
© www.soinside.com 2019 - 2024. All rights reserved.