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;
我期望即使刷新后列表也会保留,但数据不会保留。
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]);
每次刷新后 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 [];
});
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;