I followed this tutorial to use localStorage in React:
import { useState, useEffect } from 'react';
function App() {
// In the original code, this is inside the `useVolume` hook
const [volumes, setVolumes] = useState([0, 0, 0]);
useEffect(() => {
const savedVolumes = localStorage.getItem('volumes');
if (savedVolumes) {
const parsedVolumes = JSON.parse(savedVolumes);
setVolumes(parsedVolumes);
}
}, []);
useEffect(() => {
localStorage.setItem('volumes', JSON.stringify(volumes));
}, [volumes]);
// In the original code, this is inside the `useVolume` hook
// with other functions that update `volumes`
const updateVolumes = () => {
const newVolumes = [0, 0, 1];
setVolumes(newVolumes);
};
return (
<div className="App">
<div>{JSON.stringify(volumes)}</div>
<button onClick={updateVolumes}>Update Volumes</button>
</div>
);
}
export default App;
When I press the Update Volumes button, the volumes
localStorage changes to [0, 0, 1]
, but when I reload the page, volumes is back to [0, 0, 0]
(localStorage is also back to [0, 0 ,0]
).
How to change this code so that volumes
and localStorage
are [0, 0, 1]
even after reloading the page?
Note: I placed volumes
, setVolumes
, and updateVolumes
in App()
to simplify the example. In the original app, they are in a hook. That’s why I decoupled localStorage from their logic. I thought keeping it separate from the hook would be a better separation of concerns.
2
Answers
The reason is because you use StrictMode
On strict mode react run your components twice which cause to reset volume in localstorge.
Remove the strict mode and it will start to work as expected. However when you design your components make sure no matter how many times it get called the result is same.
I would recommend you to read the documentation instead of those old tutorials. https://react.dev/reference/react/useEffect
UPDATED
You don’t need that 2nd useEffect. We exactly know when the volumes is about to update. So just save it in the eventhandler
Notice I used
newVolumes
not thevolumes
becausesetVolumes
does not update the state but just schedule an update to do later. So thevolumes
is still holding the old state.Check this for more info – https://react.dev/learn/you-might-not-need-an-effect
let’s walk through your code and you’ll see why thats happening. you are setting the state by default to [0, 0, 0] on mount both useEffect will run essentially overwriting whatever was in localstorage what you can do is something like this
where you only set default value conditionally if local storage is empty