« All posts

React useLocalStorage: SSR-Safe Persistent State Hook

A look at the four hidden bugs in hand-rolled useState+useEffect localStorage patterns, and how the useLocalStorage hook fixes SSR, sync, and serialization issues.

The common useState + useEffect + localStorage pattern developers use to persist things like dashboard filters is far more fragile than it looks. It hides four distinct bugs: crashes or hydration mismatches under server-side rendering, exceptions on corrupted JSON, no synchronization across browser tabs, and components sharing the same key silently drifting out of sync with each other.

The useLocalStorage hook from @reactuses/core mirrors useState's interface exactly while solving all of these at the hook level. Built on React's useSyncExternalStore primitive, it returns the default value during server rendering, avoiding both crashes and hydration warnings. It auto-serializes objects, Maps, Sets, and Dates, supports removing a key entirely via setValue(null), and gracefully falls back to in-memory state with an onError callback when storage is unavailable.

It also listens to the native storage event for cross-tab sync by default, and re-broadcasts its own writes internally so that multiple components reading the same key inside a single tab always stay consistent with one another.

For React teams that would rather hand persistent state management to a tested, TypeScript-first API than hand-roll it, this kind of hook offers a practical reference — particularly valuable in SSR applications where it preempts hydration errors before they happen.

» SourceDev.to