React usePersistedState hook
Returns a stateful value, persisted in localStorage
, and a function to update it.
- Use the
useState()
hook to initialize thevalue
todefaultValue
. - Use the
useRef()
hook to create a ref that will hold thename
of the value inWindow.localStorage
. - Use 3 instances of the
useEffect()
hook for initialization,value
change andname
change respectively. - When the component is first mounted, use
Storage.getItem()
to updatevalue
if there's a stored value orStorage.setItem()
to persist the current value. - When
value
is updated, useStorage.setItem()
to store the new value. - When
name
is updated, useStorage.setItem()
to create the new key, update thenameRef
and useStorage.removeItem()
to remove the previous key fromWindow.localStorage
.
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]; }; const MyComponent = ({ name }) => { const [val, setVal] = usePersistedState(name, 10); return ( <input value={val} onChange={e => { setVal(e.target.value); }} /> ); }; const MyApp = () => { const [name, setName] = React.useState('my-value'); return ( <> <MyComponent name={name} /> <input value={name} onChange={e => { setName(e.target.value); }} /> </> ); }; ReactDOM.createRoot(document.getElementById('root')).render( <MyApp /> );