React hooks for localStorage and sessionStorage — JSON serialization, custom serializer/parser, key prefix namespacing, and real-time cross-tab sync. SSR-safe with zero direct dependencies.
- 🪝
useState-like API — drop-in replacement with the same[value, setValue]tuple - 🔄 Cross-tab sync — state stays in sync across browser tabs via the native
storageevent - 🧩 Custom serializer/parser — store
Date,Map, or any custom type - 📦 JSON by default — objects and arrays work out of the box
- 🏷️ Key prefix — namespace storage keys per app via
<StorageProvider> - 🌐 SSR-safe — no
windowaccess during render, works with Next.js and Remix - 🪶 Tiny bundle — zero runtime dependencies, tree-shakable ESM
- 💪 TypeScript first — fully typed with generics
npm install --save @guoyunhe/react-storageimport { useLocalStorage, useSessionStorage } from '@guoyunhe/react-storage';
function App() {
const [settings, setSettings] = useLocalStorage('settings', {
theme: 'dark',
fontSize: 14,
});
const [draft, setDraft] = useSessionStorage('draft', '');
}Use serializer and parser to handle non-JSON types:
const [date, setDate] = useLocalStorage('date', new Date(), {
serializer: (d) => d.toISOString(),
parser: (s) => new Date(s),
});Scope storage keys per app to avoid collisions:
import { StorageProvider, useLocalStorage } from '@guoyunhe/react-storage';
function App() {
return (
<StorageProvider prefix='dashboard_'>
<Dashboard />
</StorageProvider>
);
}
function Dashboard() {
// actual key: "dashboard_theme"
const [theme, setTheme] = useLocalStorage('theme', 'light');
}Set defaults once at the top level:
<StorageProvider serializer={mySerializer} parser={myParser} prefix='app_'>
<App />
</StorageProvider>All components reading the same key stay in sync — even across tabs:
function Counter() {
const [count, setCount] = useLocalStorage('count', 0);
return (
<div>
<button onClick={() => setCount((c) => c - 1)}>−</button>
<span>{count}</span>
<button onClick={() => setCount((c) => c + 1)}>+</button>
</div>
);
}
// Render multiple <Counter /> — they all share the same stateReturns [value, setValue] — same shape as useState. Values persist in localStorage and sync across tabs.
Same API as useLocalStorage, but stores in sessionStorage. Data is cleared when the tab closes. Useful for draft forms, wizard state, and ephemeral UI state.
| Option | Type | Default | Description |
|---|---|---|---|
serializer |
(value: T) => string |
JSON.stringify |
Custom serialize function |
parser |
(raw: string) => T |
JSON.parse |
Custom parse function |
prefix |
string |
'' |
Override the global prefix for this key |
Provides global defaults for all hooks within its subtree.
| Prop | Type | Default | Description |
|---|---|---|---|
serializer |
(value: any) => string |
JSON.stringify |
Global serializer |
parser |
(raw: string) => any |
JSON.parse |
Global parser |
prefix |
string |
'' |
Global key prefix |
| @guoyunhe/react-storage | use-local-storage-state | usehooks-ts | react-use | ahooks | |
|---|---|---|---|---|---|
| React peer | >=16.8 |
>=18 |
>=16.8 |
* |
>=16.8 |
| Dependencies | 0 | 0 | 1 | 14 | 10 |
| Local + Session | ✅ | ❌ | ✅ | ✅ | ✅ |
| Cross-tab sync | ✅ | ✅ | ❌ | ❌ | ✅ |
| Key prefix | ✅ | ❌ | ❌ | ❌ | ❌ |
| Custom serializer | ✅ | ✅ | ✅ | ❌ | ✅ |
| Typed API | ✅ | ✅ | ✅ | ✅ | ✅ |
| ESM | ✅ | ✅ | ✅ | ✅ | ✅ |