useLocalStorageLoading saved progress…

useLocalStorage

useLocalStorage is useState that remembers. It works exactly like useStateconst [value, setValue] = useLocalStorage(key, initial) — but the value is persisted to localStorage, so it survives a page reload, and it stays in sync across browser tabs. It's the go-to hook for a theme preference, a "dismissed" flag, or a draft the user shouldn't lose.

Implement useLocalStorage(key, initialValue). On first render, read the stored value (or fall back to initialValue). setValue updates React state and writes to localStorage, accepting a value or an updater function. Listen for the storage event so a change in another tab updates this one.

Signature

function useLocalStorage(key, initialValue) {
  // returns [value, setValue] — like useState, backed by localStorage.
}

Examples

const [name, setName] = useLocalStorage('name', 'Guest');
setName('Ada');           // state updates AND localStorage['name'] = '"Ada"'
// reload the page -> name is 'Ada'
const [count, setCount] = useLocalStorage('count', 0);
setCount((c) => c + 1);   // functional updater, like useState

Notes

  • Read on init (lazy) — use a lazy initializer so localStorage is read once on mount, not on every render. Parse the stored JSON; fall back to initialValue if the key is absent.
  • Write on setsetValue must update state and JSON.stringify the value into localStorage.
  • Functional updaters — support setValue(prev => next) like useState.
  • Cross-tab sync — subscribe to the window storage event (fired in other tabs) and update state when it matches your key; clean up the listener on unmount.
  • Be defensive — wrap storage access in try/catch (private mode, quota, SSR where window is undefined) and fall back gracefully.
Loading editor…