All hooks / Storage and URL
useLocalStorage
State that persists in localStorage as JSON, stays in sync across components and browser tabs, and is safe to server-render.
Renders serverValue on the server and during hydration, then switches to the stored value with no hydration mismatch. Missing or unparseable stored values also read as serverValue. Setting undefined removes the key.
Values go through JSON: a Date comes back as a string, and Map, Set, Infinity, and undefined inside objects don't survive. Store plain data. Writes made directly with localStorage in the same tab aren't seen; go through the setter.
Import
import { useLocalStorage } from '@vincent.ri/react-tils'
// or only this hook
import { useLocalStorage } from '@vincent.ri/react-tils/useLocalStorage'Usage
const [theme, setTheme] = useLocalStorage<'light' | 'dark'>('theme', 'light')
setTheme('dark')
const [count, setCount] = useLocalStorage('count', 0)
setCount((c) => c + 1)Live demo
Reload: both stay. Open a second tab: local syncs, session does not.
When to use it
User preferences, drafts, or UI state should survive a reload or be shared between tabs (theme, sidebar open, last tab).
When not to
The data is sensitive (tokens, personal data). Any script on the page can read localStorage. Also not for large data (5 MB limit, blocks the main thread); use IndexedDB. Not for server-needed state; use cookies.
API
function useLocalStorage<T>(key: string, serverValue: T): [T, SetValue<T>]| Parameter | Description |
|---|---|
key | The localStorage key. |
serverValue | Value on the server, during hydration, and when nothing valid is stored. Pass a primitive or a constant, so the setter stays stable. |
Returns [value, setValue], like useState. setValue accepts a value or an updater. If storage is full or blocked, the value still updates for this page session but isn't saved.
Browser support
| Uses | Chrome | Edge | Firefox | Safari | Chrome Android | Safari iOS |
|---|---|---|---|---|---|---|
| localStorageWidely available | 4+ | 12+ | 3.5+ | 4+ | 18+ | 3.2+ |
| storage eventWidely available | 1+ | 15+ | 45+ | 4+ | 18+ | 4+ |
First version with support, from MDN's compatibility data (web-features 3.42.0, @mdn/browser-compat-data 8.1.5).
Coming from another library?
Other libraries call this useLocalStorageState.