useLocalStorage
React hook that uses the localStorage API to persist state across page reloads with automatic serialization and deserialization.
Installation
npx shadcn@latest add https://www.shadcn.io/registry/use-local-storage.json
npx shadcn@latest add https://www.shadcn.io/registry/use-local-storage.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/use-local-storage.json
bunx shadcn@latest add https://www.shadcn.io/registry/use-local-storage.json
Features
- Persistent state - State survives page reloads and browser sessions
- Automatic serialization - JSON serialization/deserialization by default
- Custom serializers - Support for custom serialization logic
- Cross-tab synchronization - Changes sync across browser tabs
- SSR compatible - Optional initialization for server-side rendering
- Type safety - Full TypeScript support with proper generics
- Error handling - Graceful fallbacks for localStorage errors
Usage
import { useLocalStorage } from "@/hooks/use-local-storage"
function Counter() {
const [count, setCount, removeCount] = useLocalStorage("counter", 0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(c => c + 1)}>Increment</button>
<button onClick={() => setCount(c => c - 1)}>Decrement</button>
<button onClick={removeCount}>Reset</button>
</div>
)
}
API Reference
useLocalStorage
Parameter | Type | Description |
---|---|---|
key | string | The key under which the value will be stored in localStorage |
initialValue | T | (() => T) | The initial value or a function that returns the initial value |
options | UseLocalStorageOptions<T> | Optional configuration for serialization and behavior |
UseLocalStorageOptions
Property | Type | Default | Description |
---|---|---|---|
serializer | (value: T) => string | JSON.stringify | Function to serialize the value before storing |
deserializer | (value: string) => T | JSON.parse | Function to deserialize the stored value |
initializeWithValue | boolean | true | Whether to initialize with stored value (set to false for SSR) |
Return Value
Returns a tuple with:
value
: The current stored valuesetValue
: Function to update the value (same API asuseState
)removeValue
: Function to remove the key from localStorage and reset to initial value
Usage Examples
Basic Usage
const [name, setName] = useLocalStorage("user-name", "")
return (
<input
value={name}
onChange={e => setName(e.target.value)}
placeholder="Enter your name"
/>
)
With Complex Objects
type User = { name: string; age: number }
const [user, setUser] = useLocalStorage<User>("user", {
name: "",
age: 0
})
const updateName = (name: string) => {
setUser(prev => ({ ...prev, name }))
}
Custom Serialization
const [date, setDate] = useLocalStorage("date", new Date(), {
serializer: date => date.toISOString(),
deserializer: str => new Date(str)
})
SSR Compatible
const [theme, setTheme] = useLocalStorage("theme", "light", {
initializeWithValue: false // Prevents hydration mismatch
})
Function Updates
const [items, setItems] = useLocalStorage<string[]>("items", [])
const addItem = (item: string) => {
setItems(prev => [...prev, item])
}
const removeItem = (index: number) => {
setItems(prev => prev.filter((_, i) => i !== index))
}
Implementation Details
- Uses
JSON.stringify
/JSON.parse
by default for serialization - Listens to both
storage
events (cross-tab) and customlocal-storage
events (same tab) - Gracefully handles localStorage errors (quota exceeded, disabled storage)
- Supports functional updates like
useState
- Handles
undefined
values correctly in serialization - Server-side rendering compatible with
initializeWithValue: false
- Automatically syncs state changes across all hook instances with the same key
useIsomorphicLayoutEffect
React hook that uses useLayoutEffect in browser and useEffect during SSR to prevent hydration warnings. Perfect for React applications requiring DOM measurements with Next.js integration and TypeScript support.
useMap
Manage key-value Map state with type-safe operations and immutable updates. Perfect for React applications requiring complex state management with Next.js integration and TypeScript support.