← Back to all snippets
JAVASCRIPT

Synchronizing React State with Local Storage using a Custom Hook

Persist and retrieve component state automatically to and from local storage using a custom React hook, ensuring data survives page reloads.

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

// Custom Hook to manage state persisted in localStorage
function useLocalStorage(key, initialValue) {
  // State to store our value
  // Pass initial state function to useState so logic is only executed once
  const [storedValue, setStoredValue] = useState(() => {
    if (typeof window === 'undefined') {
      return initialValue;
    }
    try {
      // Get from local storage by key
      const item = window.localStorage.getItem(key);
      // Parse stored json or if none return initialValue
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      // If error, return initialValue
      console.error(error);
      return initialValue;
    }
  });

  // useEffect to update local storage when the state changes
  useEffect(() => {
    if (typeof window !== 'undefined') {
      try {
        window.localStorage.setItem(key, JSON.stringify(storedValue));
      } catch (error) {
        console.error(error);
      }
    }
  }, [key, storedValue]);

  return [storedValue, setStoredValue];
}

// Example Component using the custom hook
function LocalStorageCounter() {
  const [count, setCount] = useLocalStorage('myAppCount', 0);

  return (
    <div style={{ padding: '20px', border: '1px solid #ccc', borderRadius: '8px' }}>
      <h1>Count: {count}</h1>
      <button onClick={() => setCount(prevCount => prevCount + 1)} style={{ marginRight: '10px', padding: '10px' }}>
        Increment
      </button>
      <button onClick={() => setCount(0)} style={{ padding: '10px' }}>
        Reset
      </button>
      <p>Try refreshing the page; the count will persist!</p>
    </div>
  );
}
How it works: The `useLocalStorage` custom hook provides a way to persist React state in the browser's local storage, ensuring that the state remains even after a page reload. It combines `useState` for managing the component's state and `useEffect` to synchronize this state with local storage. The initial state is loaded from local storage (if present), and any subsequent changes to the state automatically update the corresponding local storage entry. This is incredibly useful for saving user preferences, form data, or simple application settings.

Need help integrating this into your project?

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

Hire DigitalCodeLabs