I have a custom hook to manage localStorage
like below:
import { useEffect, useState } from 'react'
export default function useLocalStorage(key, initValue) {
const [state, setState] = useState(() => {
const value = localStorage.getItem(key);
if (value !== null) {
return JSON.parse(value);
}
localStorage.setItem(key, JSON.stringify(initValue));
return initValue;
})
useEffect(() => {
localStorage.setItem(key, state);
}, [key, state])
return [state, setState];
}
This custom hook is declared to use the same localstorage key for two or more components in one screen. e,g.
const [state, setState] = useLocalStorage('key', false);
At this time, since components using useLocalStorage
want to work according to the state change of localStorage
, we try to use the state returned by useLocalStorage
as the second parameter of useEffect
.
useEffect(() => {
foobar()
}, [state]);
I expected the foobar()
function in useEffect
to work when the "state" changes in all components that declared this useEffect
. However, foobar()
only worked for one component out of several components using this same useEffect
.Why this is happening? How do I get it to work the way I want it to?
CodePudding user response:
You should listen the local storage changes in order to have the updated value. For example this way:
import { useEffect, useState } from 'react'
export default function useLocalStorage(key, initValue) {
const [state, setState] = useState(() => {
const value = localStorage.getItem(key);
if (value !== null) {
return JSON.parse(value);
}
localStorage.setItem(key, JSON.stringify(initValue));
window.dispatchEvent(new Event("storage");
return initValue;
});
useEffect(() => {
localStorage.setItem(key, state);
window.dispatchEvent(new Event("storage");
}, [key, state]);
useEffect(() => {
const listenStorageChange = () => {
setState(() => {
const value = localStorage.getItem(key);
if (value !== null) {
return JSON.parse(value);
}
localStorage.setItem(key, JSON.stringify(initValue));
window.dispatchEvent(new Event("storage");
return initValue;
});
};
window.addEventListener("storage", listenStorageChange);
return () => window.removeEventListener("storage", listenStorageChange);
}, []);
return [state, setState];
}