← Back to all snippets
JAVASCRIPT

Persist State with `useLocalStorage` React Hook

Create a `useLocalStorage` hook to effortlessly synchronize and persist React state with the browser's local storage, ensuring data remains available across page reloads.

import { useState, useEffect, useCallback } from 'react';

function useLocalStorage(key, initialValue) {
  const readValue = useCallback(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.warn(`Error reading localStorage key "${key}":`, error);
      return initialValue;
    }
  }, [key, initialValue]);

  const [storedValue, setStoredValue] = useState(readValue);

  const setValue = useCallback((value) => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.warn(`Error setting localStorage key "${key}":`, error);
    }
  }, [key, storedValue]);

  useEffect(() => {
    setStoredValue(readValue());
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []); // Only run once on mount to handle initial value correctly

  return [storedValue, setValue];
}

// Example Usage:
/*
function ThemeSwitcher() {
  const [theme, setTheme] = useLocalStorage('app-theme', 'light');

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };

  return (
    <div>
      <p>Current Theme: {theme}</p>
      <button onClick={toggleTheme}>Toggle Theme</button>
    </div>
  );
}
*/
How it works: The `useLocalStorage` hook initializes state from `localStorage` on component mount and automatically updates `localStorage` whenever the state changes. It takes a `key` and an `initialValue`. The `useState` is initialized using a `readValue` function to parse the stored JSON or use the `initialValue`. The `setValue` function updates both the React state and `localStorage`, handling function-based state updates. This provides a seamless way to persist small pieces of data across user sessions.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs