Join our Discord Community

useLocalStorage

React hook that uses the localStorage API to persist state across page reloads with automatic serialization and deserialization.

Loading component...

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

ParameterTypeDescription
keystringThe key under which the value will be stored in localStorage
initialValueT | (() => T)The initial value or a function that returns the initial value
optionsUseLocalStorageOptions<T>Optional configuration for serialization and behavior

UseLocalStorageOptions

PropertyTypeDefaultDescription
serializer(value: T) => stringJSON.stringifyFunction to serialize the value before storing
deserializer(value: string) => TJSON.parseFunction to deserialize the stored value
initializeWithValuebooleantrueWhether to initialize with stored value (set to false for SSR)

Return Value

Returns a tuple with:

  • value: The current stored value
  • setValue: Function to update the value (same API as useState)
  • 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 custom local-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