← back to Watches

src/hooks/useLocalStorage.js

57 lines

import { useState, useEffect } from 'react';

/**
 * Custom hook for localStorage with SSR safety
 * Usage: const [value, setValue] = useLocalStorage('key', defaultValue);
 */
export function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    if (typeof window === 'undefined') {
      return initialValue;
    }
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(`Error loading ${key} from localStorage:`, error);
      return initialValue;
    }
  });

  const setValue = (value) => {
    try {
      const valueToStore = value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      if (typeof window !== 'undefined') {
        window.localStorage.setItem(key, JSON.stringify(valueToStore));
      }
    } catch (error) {
      console.error(`Error saving ${key} to localStorage:`, error);
    }
  };

  return [storedValue, setValue];
}

/**
 * Custom hook for dark mode with system preference detection
 */
export function useDarkMode() {
  const [darkMode, setDarkMode] = useLocalStorage('darkMode', null);

  useEffect(() => {
    if (darkMode === null && typeof window !== 'undefined') {
      const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
      setDarkMode(prefersDark);
    }
  }, [darkMode, setDarkMode]);

  useEffect(() => {
    if (typeof window !== 'undefined' && darkMode !== null) {
      document.documentElement.classList.toggle('dark', darkMode);
    }
  }, [darkMode]);

  return [darkMode, setDarkMode];
}