Whenever a new item is added to the list, the local storage is updated but if i refresh the page. The key remains but the value is reset to an empty array.
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;
I was expecting the list to remain even after a refresh but the data does not persist.
4
Answers
These two useEffect hooks conflict each other
My solution is to create a new flag that check whether the data is loaded from localstorage or not
setData
is asynchronous. ThelocalStorage.setItem
not. The function from the seconduseEffect
will be called beforesetData
from the firstuseEffect
causing yourlocalStorage
to be overwritten with empty array, because in that momentdata
is[]
.Since
localStorage.setItem
is synchronous, I would suggest you to remove the firstuseEffect
completely and move the logic directly to theuseState
hook to make it a default value.check if the data variable has data in it, because the useEffect that watches data is called on the first render.
better approach :
stakblitz example : https://stackblitz.com/edit/react-bhdhmy?file=src%2FApp.js
Removed Second useEffect: The second useEffect which was updating the local storage whenever data changed has been removed.
Added handleSetData Function: Introduced a new function called handleSetData that both updates the data state and saves this new data directly to local storage. This makes sure local storage stays in sync with state updates without the need for a useEffect.
Modified handleAddItem Function: Refactored the handleAddItem function to use the new handleSetData function, ensuring that when a new item is added, it is both added to the state and saved to local storage.
Added handleDeleteAll Function: Introduced a new function to clear all items. This function sets the data state to an empty array and also updates the local storage to reflect this change.
UI Additions: Added a new button to the component’s return JSX that invokes handleDeleteAll when clicked, allowing users to clear all items.
You can remove second the useEffect part and save the data in handleAddItem function.
Here is the full code you require.
That should be worked.