I was working on a project using Recoil for state management in React.
I needed to persist some state to localStorage, and there’s some info on how to do it in Recoil’s docs.
That works; however it doesn’t respond to state changes from other instances of your app in multiple browser tabs.
If you want that, you have to add the code yourself by leveraging the storage event.
Or, you can just copy the code I made to do it.
import { AtomEffect } from 'recoil';
export const localStorageEffect =
<T>(key: string): AtomEffect<T> =>
({ setSelf, onSet, resetSelf }) => {
const savedValue = localStorage.getItem(key);
if (savedValue != null) {
setSelf(JSON.parse(savedValue));
}
onSet((newValue, _, isReset) => {
isReset ? localStorage.removeItem(key) : localStorage.setItem(key, JSON.stringify(newValue));
});
const handleStorageChange = (event: StorageEvent) => {
if (event.key === key) {
if (event.newValue === null) {
resetSelf();
} else {
const newValue = JSON.parse(event.newValue);
setSelf(newValue);
}
}
};
window.addEventListener('storage', handleStorageChange);
return () => {
window.removeEventListener('storage', handleStorageChange);
};
};
Usage:
const myAtom = atom({
key: 'myAtom',
default: 1,
effects: [
localStorageEffect('my-atom-local-storage-key'),
]
});
Happy coding!