Returns a stateful value, persisted in localStorage
, and a function to update it.
- Use the
useState()
hook to initialize the value todefaultValue
. - Use the
useRef()
hook to create a ref that will hold the name of the value inWindow.localStorage.
- Use 3 instances of the
useEffect()
hook for initialization, value change and name change respectively. - When the component is first mounted, use
Storage.getItem()
to update value if there's a stored value orStorage.setItem()
to persist the current value. - When value is updated, use
Storage.setItem()
to store the new value. - When name is updated, use
Storage.setItem()
to create the new key, update the nameRef and useStorage.removeItem()
to remove the previous key fromWindow.localStorage.
- Note: The hook is meant for use with primitive values (i.e. not objects) and doesn't account for changes to
Window.localStorage
due to other code. Both of these issues can be easily handled (e.g. JSON serialization and handling the 'storage' event).
const usePersistedState = (name, defaultValue) => {
const [value, setValue] = React.useState(defaultValue);
const nameRef = React.useRef(name);
React.useEffect(() => {
try {
const storedValue = localStorage.getItem(name);
if (storedValue !== null) setValue(storedValue);
else localStorage.setItem(name, defaultValue);
} catch {
setValue(defaultValue);
}
}, []);
React.useEffect(() => {
try {
localStorage.setItem(nameRef.current, value);
} catch {}
}, [value]);
React.useEffect(() => {
const lastName = nameRef.current;
if (name !== lastName) {
try {
localStorage.setItem(name, value);
nameRef.current = name;
localStorage.removeItem(lastName);
} catch {}
}
}, [name]);
return [value, setValue];
};