Persisting state in React
Sometimes, you might want to persist the state of your React components across page reloads. You can achieve this by using the localStorage
or sessionStorage
APIs. But creating custom hooks for this use case might get a little tricky.
useLocalStorage
hook
In order to persist a stateful value to localStorage
, you can create a custom hook called useLocalStorage
. This hook will return a stateful value and a function to update it.
Implementing the hook requires you to use the useState()
hook with a function to initialize its value lazily. You can then use a try...catch
block and Storage.getItem()
to try and get the value from Window.localStorage
. If no value is found, use Storage.setItem()
to store the defaultValue
and use it as the initial state. If an error occurs, use defaultValue
as the initial state. Finally, define a function that will update the state variable with the passed value and use Storage.setItem()
to store it.
const useLocalStorage = (keyName, defaultValue) => { const [storedValue, setStoredValue] = React.useState(() => { try { const value = window.localStorage.getItem(keyName); if (value) { return JSON.parse(value); } else { window.localStorage.setItem(keyName, JSON.stringify(defaultValue)); return defaultValue; } } catch (err) { return defaultValue; } }); const setValue = newValue => { try { window.localStorage.setItem(keyName, JSON.stringify(newValue)); } catch (err) {} setStoredValue(newValue); }; return [storedValue, setValue]; }; const MyApp = () => { const [name, setName] = useLocalStorage('name', 'John'); return <input value={name} onChange={e => setName(e.target.value)} />; }; ReactDOM.createRoot(document.getElementById('root')).render( <MyApp /> );
useSessionStorage
hook
The exact same logic can be applied to persist a stateful value to sessionStorage
. You can create a custom hook called useSessionStorage
that returns a stateful value and a function to update it. The only difference is that you'll be using Window.sessionStorage
instead of Window.localStorage
.
const useSessionStorage = (keyName, defaultValue) => { const [storedValue, setStoredValue] = React.useState(() => { try { const value = window.sessionStorage.getItem(keyName); if (value) { return JSON.parse(value); } else { window.sessionStorage.setItem(keyName, JSON.stringify(defaultValue)); return defaultValue; } } catch (err) { return defaultValue; } }); const setValue = newValue => { try { window.sessionStorage.setItem(keyName, JSON.stringify(newValue)); } catch (err) {} setStoredValue(newValue); }; return [storedValue, setValue]; }; const MyApp = () => { const [name, setName] = useSessionStorage('name', 'John'); return <input value={name} onChange={e => setName(e.target.value)} />; }; ReactDOM.createRoot(document.getElementById('root')).render( <MyApp /> );