Jump to Table of ContentsJump to Content
⚛️
React
🏷️2 tags

A custom React Hook that synchronizes component state with localStorage, following the DRY principle. This hook encapsulates localStorage logic, making it reusable across multiple components for cleaner and more maintainable code.

⚛️ Hook Declaration

import React, { useState, useEffect, useRef } from "react";

function useLocalStorageState(
  key,
  defaultValue = '',
  { serialize = JSON.stringify, deserialize = JSON.parse } = {},
) {
  // Initialize state with local storage value (if available) or default value
  const [state, setState] = useState(() => {
    const valueInLocalStorage = window.localStorage.getItem(key);
    if (valueInLocalStorage) {
      return deserialize(valueInLocalStorage);
    }
    // If default value is a function, execute it, else return default value
    return typeof defaultValue === 'function' ? defaultValue() : defaultValue;
  });

  // Ref to keep track of previous key
  const prevKeyRef = useRef(key);

  // Effect to update local storage when state or key changes
  useEffect(() => {
    // Retrieve previous key
    const prevKey = prevKeyRef.current;
    // If key has changed, remove previous key from local storage
    if (prevKey !== key) {
      window.localStorage.removeItem(prevKey);
    }
    // Update ref with current key
    prevKeyRef.current = key;
    // Set current state to local storage
    window.localStorage.setItem(key, serialize(state));
  }, [key, state, serialize]);

  // Return state and setState function
  return [state, setState];
}

export { useLocalStorageState };

🛠️ Hook Implementation

function YourComponentNameWhereYouNeed(props) {
  // Example usage from a real project
  const [localLogs, setLocalLogs] = useLocalStorageState('localLogs')

   return (
      <div>
         {/* Your component content */}
      </div>
   )
}

🔑 Key Features

  • Automatic Synchronization: State changes are automatically saved to localStorage
  • Serialization Support: Configurable serialization/deserialization methods
  • Dynamic Keys: Handles localStorage key changes gracefully
  • Default Values: Supports both static values and factory functions
  • SSR Safe: Properly handles server-side rendering scenarios

💡 Use Cases

Perfect for persisting:

  • User preferences and settings
  • Form data and drafts
  • Shopping cart contents
  • Theme preferences
  • Authentication tokens
  • Any state that should survive page refreshes

📝 Advanced Usage

// With custom serialization
const [complexData, setComplexData] = useLocalStorageState('complexData', {}, {
  serialize: (value) => JSON.stringify(value),
  deserialize: (value) => JSON.parse(value)
});

// With factory function as default
const [timestamp, setTimestamp] = useLocalStorageState('timestamp', () => Date.now());

Tags