# use-local-storage-state `use-local-storage-state` is a lightweight React hook that provides persistent state management using the browser's localStorage API. It offers a drop-in replacement for React's `useState` with automatic persistence, SSR support, and synchronization across browser tabs. The library handles edge cases gracefully including localStorage quota errors, private browsing mode restrictions, and invalid stored data. The hook weighs just 689 bytes (brotli compressed) and is production-ready with support for React 18+ concurrent rendering and React 19. It provides an in-memory fallback when localStorage is unavailable, cross-tab synchronization via the Window `storage` event, and TypeScript support out of the box. The API design mirrors `useState` to minimize learning curve while extending it with additional utilities like `removeItem` and `isPersistent` for complete control over persisted state. ## Basic Usage The `useLocalStorageState` hook works like `useState` but persists data to localStorage. It accepts a key string and an options object with a default value. ```typescript import useLocalStorageState from 'use-local-storage-state' export default function Todos() { const [todos, setTodos] = useLocalStorageState('todos', { defaultValue: ['buy avocado', 'do 50 push-ups'] }) const addTodo = (newTodo: string) => { setTodos([...todos, newTodo]) } const clearTodos = () => { setTodos([]) } return (
) } ``` ## Updating State with Callback Function Like `useState`, the setter function accepts either a new value or a callback function that receives the current value and returns the new value. This is useful for updates based on the previous state. ```typescript import useLocalStorageState from 'use-local-storage-state' export default function Counter() { const [count, setCount] = useLocalStorageState('counter', { defaultValue: 0 }) const increment = () => { setCount((prevCount) => prevCount + 1) } const decrement = () => { setCount((prevCount) => prevCount - 1) } const reset = () => { setCount(0) } return (

Count: {count}

) } ``` ## Lazy Default Value Initialization The `defaultValue` option accepts a lazy initializer function (like `useState`). This is useful when computing the default value is expensive, as it only runs once on initial mount. ```typescript import useLocalStorageState from 'use-local-storage-state' export default function ExpensiveComponent() { const [data, setData] = useLocalStorageState('expensive-data', { defaultValue: () => { // This expensive computation only runs if no stored value exists console.log('Computing expensive default...') return Array.from({ length: 100 }, (_, i) => ({ id: i, value: Math.random() })) } }) return
Items: {data.length}
} ``` ## Using removeItem to Reset State The hook returns a third value containing `removeItem()` and `isPersistent`. The `removeItem()` function clears the localStorage entry and resets the state to its default value. ```typescript import useLocalStorageState from 'use-local-storage-state' export default function UserPreferences() { const [preferences, setPreferences, { removeItem }] = useLocalStorageState('user-prefs', { defaultValue: { theme: 'light', fontSize: 16, notifications: true } }) const updateTheme = (theme: string) => { setPreferences({ ...preferences, theme }) } const resetToDefaults = () => { removeItem() // Clears localStorage and resets to defaultValue } return (

Theme: {preferences.theme}

) } ``` ## Checking Persistence Status with isPersistent The `isPersistent` property indicates whether data is being stored in localStorage or only in memory (fallback). This is useful for notifying users when their data won't persist (e.g., in private browsing mode or when storage quota is exceeded). ```typescript import useLocalStorageState from 'use-local-storage-state' export default function PersistentForm() { const [formData, setFormData, { isPersistent }] = useLocalStorageState('draft-form', { defaultValue: { name: '', email: '', message: '' } }) const updateField = (field: string, value: string) => { setFormData({ ...formData, [field]: value }) } return (
{!isPersistent && (
⚠️ Your changes won't be saved between sessions. Please enable cookies/localStorage.
)} updateField('name', e.target.value)} placeholder="Name" /> updateField('email', e.target.value)} placeholder="Email" />