"use client"; import { useCallback, useSyncExternalStore } from "react"; type Listener = () => void; const listeners = new Map>(); const cache = new Map(); function readFromStorage(key: string, initial: T): T { try { const raw = window.localStorage.getItem(key); return raw != null ? (JSON.parse(raw) as T) : initial; } catch { return initial; } } function notify(key: string) { listeners.get(key)?.forEach((l) => l()); } /** * State, der in localStorage persistiert wird. * SSR-sicher über useSyncExternalStore: liefert serverseitig `initial`, * hydriert clientseitig aus localStorage. */ export function useLocalStorage(key: string, initial: T) { const subscribe = useCallback( (callback: Listener) => { let set = listeners.get(key); if (!set) { set = new Set(); listeners.set(key, set); } set.add(callback); return () => set!.delete(callback); }, [key], ); const getSnapshot = useCallback(() => { if (!cache.has(key)) cache.set(key, readFromStorage(key, initial)); return cache.get(key) as T; // eslint-disable-next-line react-hooks/exhaustive-deps -- `initial` is only used as a one-time fallback }, [key]); const getServerSnapshot = useCallback(() => initial, [initial]); const value = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); const setValue = useCallback( (next: T | ((prev: T) => T)) => { const prev = cache.has(key) ? (cache.get(key) as T) : readFromStorage(key, initial); const resolved = typeof next === "function" ? (next as (p: T) => T)(prev) : next; cache.set(key, resolved); try { window.localStorage.setItem(key, JSON.stringify(resolved)); } catch { // Speicher voll o.ä. – egal } notify(key); }, [key, initial], ); return [value, setValue] as const; }