---
title: React usePersistedState hook
tags: hooks,state,effect
author: chalarangelo
cover: red-berries
firstSeen: 2020-11-29T14:16:36+02:00
lastUpdated: 2021-10-13T19:29:39+02:00
---
Returns a stateful value, persisted in `localStorage`, and a function to update it.
- Use the `useState()` hook to initialize the `value` to `defaultValue`.
- Use the `useRef()` hook to create a ref that will hold the `name` of the value in `Window.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 or `Storage.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 use `Storage.removeItem()` to remove the previous key from `Window.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).
```jsx
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];
};
```
```jsx
const MyComponent = ({ name }) => {
const [val, setVal] = usePersistedState(name, 10);
return (
{
setVal(e.target.value);
}}
/>
);
};
const MyApp = () => {
const [name, setName] = React.useState('my-value');
return (
<>
{
setName(e.target.value);
}}
/>
>
);
};
ReactDOM.createRoot(document.getElementById('root')).render(
);
```