@usefy/use-local-storage 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/useLocalStorage.ts"],"sourcesContent":["export {\r\n useLocalStorage,\r\n type UseLocalStorageOptions,\r\n type UseLocalStorageReturn,\r\n type InitialValue,\r\n} from \"./useLocalStorage\";\r\n","import { useCallback, useEffect, useRef, useState } from \"react\";\r\n\r\n/**\r\n * Type for initial value that can be a value or a function returning a value (lazy initialization)\r\n */\r\nexport type InitialValue<T> = T | (() => T);\r\n\r\n/**\r\n * Options for useLocalStorage hook\r\n */\r\nexport interface UseLocalStorageOptions<T> {\r\n /**\r\n * Custom serializer function for converting value to string\r\n * @default JSON.stringify\r\n */\r\n serializer?: (value: T) => string;\r\n /**\r\n * Custom deserializer function for parsing stored string to value\r\n * @default JSON.parse\r\n */\r\n deserializer?: (value: string) => T;\r\n /**\r\n * Whether to sync value across browser tabs via storage event\r\n * @default true\r\n */\r\n syncTabs?: boolean;\r\n /**\r\n * Callback function called when an error occurs\r\n */\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Return type for useLocalStorage hook - tuple similar to useState\r\n */\r\nexport type UseLocalStorageReturn<T> = readonly [\r\n /** Current stored value */\r\n T,\r\n /** Function to update the value (same signature as useState setter) */\r\n React.Dispatch<React.SetStateAction<T>>,\r\n /** Function to remove the value from localStorage */\r\n () => void\r\n];\r\n\r\n/**\r\n * Helper function to resolve initial value (supports lazy initialization)\r\n */\r\nfunction resolveInitialValue<T>(initialValue: InitialValue<T>): T {\r\n return typeof initialValue === \"function\"\r\n ? (initialValue as () => T)()\r\n : initialValue;\r\n}\r\n\r\n/**\r\n * A hook for persisting state in localStorage with automatic synchronization.\r\n * Works like useState but persists the value in localStorage.\r\n *\r\n * @template T - The type of the stored value\r\n * @param key - The localStorage key to store the value under\r\n * @param initialValue - Initial value or function returning initial value (lazy initialization)\r\n * @param options - Configuration options for serialization, sync, and error handling\r\n * @returns A tuple of [storedValue, setValue, removeValue]\r\n *\r\n * @example\r\n * ```tsx\r\n * // Basic usage with string\r\n * function ThemeToggle() {\r\n * const [theme, setTheme, removeTheme] = useLocalStorage('theme', 'light');\r\n *\r\n * return (\r\n * <div>\r\n * <p>Current theme: {theme}</p>\r\n * <button onClick={() => setTheme('dark')}>Dark</button>\r\n * <button onClick={() => setTheme('light')}>Light</button>\r\n * <button onClick={removeTheme}>Reset</button>\r\n * </div>\r\n * );\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // With object type\r\n * interface UserSettings {\r\n * notifications: boolean;\r\n * language: string;\r\n * }\r\n *\r\n * const [settings, setSettings] = useLocalStorage<UserSettings>('settings', {\r\n * notifications: true,\r\n * language: 'en',\r\n * });\r\n *\r\n * // Functional update\r\n * setSettings(prev => ({ ...prev, notifications: false }));\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // With lazy initialization\r\n * const [config, setConfig] = useLocalStorage('config', () => computeExpensiveDefault());\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // With custom serializer/deserializer\r\n * const [date, setDate] = useLocalStorage<Date>('lastVisit', new Date(), {\r\n * serializer: (d) => d.toISOString(),\r\n * deserializer: (s) => new Date(s),\r\n * });\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // With error handling\r\n * const [value, setValue] = useLocalStorage('key', 'default', {\r\n * onError: (error) => console.error('Storage error:', error),\r\n * });\r\n * ```\r\n */\r\nexport function useLocalStorage<T>(\r\n key: string,\r\n initialValue: InitialValue<T>,\r\n options: UseLocalStorageOptions<T> = {}\r\n): UseLocalStorageReturn<T> {\r\n const {\r\n serializer = JSON.stringify,\r\n deserializer = JSON.parse,\r\n syncTabs = true,\r\n onError,\r\n } = options;\r\n\r\n // Store options in refs for stable references and access to latest values\r\n const serializerRef = useRef(serializer);\r\n const deserializerRef = useRef(deserializer);\r\n const onErrorRef = useRef(onError);\r\n serializerRef.current = serializer;\r\n deserializerRef.current = deserializer;\r\n onErrorRef.current = onError;\r\n\r\n // Store initialValue in ref for use in removeValue and storage event handler\r\n const initialValueRef = useRef(initialValue);\r\n initialValueRef.current = initialValue;\r\n\r\n // SSR check - check once at module level for consistency\r\n const isClient = typeof window !== \"undefined\";\r\n\r\n // Lazy initialization with localStorage read\r\n const [storedValue, setStoredValue] = useState<T>(() => {\r\n if (!isClient) {\r\n return resolveInitialValue(initialValue);\r\n }\r\n\r\n try {\r\n const item = window.localStorage.getItem(key);\r\n if (item !== null) {\r\n return deserializerRef.current(item);\r\n }\r\n return resolveInitialValue(initialValue);\r\n } catch (error) {\r\n onErrorRef.current?.(error as Error);\r\n return resolveInitialValue(initialValue);\r\n }\r\n });\r\n\r\n // Store current value in ref for stable setValue reference\r\n const storedValueRef = useRef<T>(storedValue);\r\n storedValueRef.current = storedValue;\r\n\r\n // setValue - stable reference (only depends on key)\r\n const setValue = useCallback<React.Dispatch<React.SetStateAction<T>>>(\r\n (value) => {\r\n try {\r\n const currentValue = storedValueRef.current;\r\n const valueToStore =\r\n value instanceof Function ? value(currentValue) : value;\r\n\r\n setStoredValue(valueToStore);\r\n\r\n if (typeof window !== \"undefined\") {\r\n window.localStorage.setItem(\r\n key,\r\n serializerRef.current(valueToStore)\r\n );\r\n }\r\n } catch (error) {\r\n onErrorRef.current?.(error as Error);\r\n }\r\n },\r\n [key]\r\n );\r\n\r\n // removeValue - stable reference\r\n const removeValue = useCallback(() => {\r\n try {\r\n const initial = resolveInitialValue(initialValueRef.current);\r\n setStoredValue(initial);\r\n\r\n if (typeof window !== \"undefined\") {\r\n window.localStorage.removeItem(key);\r\n }\r\n } catch (error) {\r\n onErrorRef.current?.(error as Error);\r\n }\r\n }, [key]);\r\n\r\n // Cross-tab synchronization via storage event\r\n useEffect(() => {\r\n if (!isClient || !syncTabs) {\r\n return;\r\n }\r\n\r\n const handleStorageChange = (event: StorageEvent) => {\r\n if (event.key !== key) {\r\n return;\r\n }\r\n\r\n if (event.newValue !== null) {\r\n try {\r\n setStoredValue(deserializerRef.current(event.newValue));\r\n } catch {\r\n // If parsing fails, reset to initial value\r\n setStoredValue(resolveInitialValue(initialValueRef.current));\r\n }\r\n } else {\r\n // Key was removed in another tab\r\n setStoredValue(resolveInitialValue(initialValueRef.current));\r\n }\r\n };\r\n\r\n window.addEventListener(\"storage\", handleStorageChange);\r\n return () => window.removeEventListener(\"storage\", handleStorageChange);\r\n }, [key, syncTabs, isClient]);\r\n\r\n // Re-read value when key changes\r\n useEffect(() => {\r\n if (!isClient) {\r\n return;\r\n }\r\n\r\n try {\r\n const item = window.localStorage.getItem(key);\r\n if (item !== null) {\r\n setStoredValue(deserializerRef.current(item));\r\n } else {\r\n setStoredValue(resolveInitialValue(initialValueRef.current));\r\n }\r\n } catch {\r\n setStoredValue(resolveInitialValue(initialValueRef.current));\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [key]);\r\n\r\n return [storedValue, setValue, removeValue] as const;\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/useLocalStorage.ts"],"sourcesContent":["export {\n useLocalStorage,\n type UseLocalStorageOptions,\n type UseLocalStorageReturn,\n type InitialValue,\n} from \"./useLocalStorage\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\n/**\n * Type for initial value that can be a value or a function returning a value (lazy initialization)\n */\nexport type InitialValue<T> = T | (() => T);\n\n/**\n * Options for useLocalStorage hook\n */\nexport interface UseLocalStorageOptions<T> {\n /**\n * Custom serializer function for converting value to string\n * @default JSON.stringify\n */\n serializer?: (value: T) => string;\n /**\n * Custom deserializer function for parsing stored string to value\n * @default JSON.parse\n */\n deserializer?: (value: string) => T;\n /**\n * Whether to sync value across browser tabs via storage event\n * @default true\n */\n syncTabs?: boolean;\n /**\n * Callback function called when an error occurs\n */\n onError?: (error: Error) => void;\n}\n\n/**\n * Return type for useLocalStorage hook - tuple similar to useState\n */\nexport type UseLocalStorageReturn<T> = readonly [\n /** Current stored value */\n T,\n /** Function to update the value (same signature as useState setter) */\n React.Dispatch<React.SetStateAction<T>>,\n /** Function to remove the value from localStorage */\n () => void\n];\n\n/**\n * Helper function to resolve initial value (supports lazy initialization)\n */\nfunction resolveInitialValue<T>(initialValue: InitialValue<T>): T {\n return typeof initialValue === \"function\"\n ? (initialValue as () => T)()\n : initialValue;\n}\n\n/**\n * A hook for persisting state in localStorage with automatic synchronization.\n * Works like useState but persists the value in localStorage.\n *\n * @template T - The type of the stored value\n * @param key - The localStorage key to store the value under\n * @param initialValue - Initial value or function returning initial value (lazy initialization)\n * @param options - Configuration options for serialization, sync, and error handling\n * @returns A tuple of [storedValue, setValue, removeValue]\n *\n * @example\n * ```tsx\n * // Basic usage with string\n * function ThemeToggle() {\n * const [theme, setTheme, removeTheme] = useLocalStorage('theme', 'light');\n *\n * return (\n * <div>\n * <p>Current theme: {theme}</p>\n * <button onClick={() => setTheme('dark')}>Dark</button>\n * <button onClick={() => setTheme('light')}>Light</button>\n * <button onClick={removeTheme}>Reset</button>\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With object type\n * interface UserSettings {\n * notifications: boolean;\n * language: string;\n * }\n *\n * const [settings, setSettings] = useLocalStorage<UserSettings>('settings', {\n * notifications: true,\n * language: 'en',\n * });\n *\n * // Functional update\n * setSettings(prev => ({ ...prev, notifications: false }));\n * ```\n *\n * @example\n * ```tsx\n * // With lazy initialization\n * const [config, setConfig] = useLocalStorage('config', () => computeExpensiveDefault());\n * ```\n *\n * @example\n * ```tsx\n * // With custom serializer/deserializer\n * const [date, setDate] = useLocalStorage<Date>('lastVisit', new Date(), {\n * serializer: (d) => d.toISOString(),\n * deserializer: (s) => new Date(s),\n * });\n * ```\n *\n * @example\n * ```tsx\n * // With error handling\n * const [value, setValue] = useLocalStorage('key', 'default', {\n * onError: (error) => console.error('Storage error:', error),\n * });\n * ```\n */\nexport function useLocalStorage<T>(\n key: string,\n initialValue: InitialValue<T>,\n options: UseLocalStorageOptions<T> = {}\n): UseLocalStorageReturn<T> {\n const {\n serializer = JSON.stringify,\n deserializer = JSON.parse,\n syncTabs = true,\n onError,\n } = options;\n\n // Store options in refs for stable references and access to latest values\n const serializerRef = useRef(serializer);\n const deserializerRef = useRef(deserializer);\n const onErrorRef = useRef(onError);\n serializerRef.current = serializer;\n deserializerRef.current = deserializer;\n onErrorRef.current = onError;\n\n // Store initialValue in ref for use in removeValue and storage event handler\n const initialValueRef = useRef(initialValue);\n initialValueRef.current = initialValue;\n\n // SSR check - check once at module level for consistency\n const isClient = typeof window !== \"undefined\";\n\n // Lazy initialization with localStorage read\n const [storedValue, setStoredValue] = useState<T>(() => {\n if (!isClient) {\n return resolveInitialValue(initialValue);\n }\n\n try {\n const item = window.localStorage.getItem(key);\n if (item !== null) {\n return deserializerRef.current(item);\n }\n return resolveInitialValue(initialValue);\n } catch (error) {\n onErrorRef.current?.(error as Error);\n return resolveInitialValue(initialValue);\n }\n });\n\n // Store current value in ref for stable setValue reference\n const storedValueRef = useRef<T>(storedValue);\n storedValueRef.current = storedValue;\n\n // setValue - stable reference (only depends on key)\n const setValue = useCallback<React.Dispatch<React.SetStateAction<T>>>(\n (value) => {\n try {\n const currentValue = storedValueRef.current;\n const valueToStore =\n value instanceof Function ? value(currentValue) : value;\n\n setStoredValue(valueToStore);\n\n if (typeof window !== \"undefined\") {\n window.localStorage.setItem(\n key,\n serializerRef.current(valueToStore)\n );\n }\n } catch (error) {\n onErrorRef.current?.(error as Error);\n }\n },\n [key]\n );\n\n // removeValue - stable reference\n const removeValue = useCallback(() => {\n try {\n const initial = resolveInitialValue(initialValueRef.current);\n setStoredValue(initial);\n\n if (typeof window !== \"undefined\") {\n window.localStorage.removeItem(key);\n }\n } catch (error) {\n onErrorRef.current?.(error as Error);\n }\n }, [key]);\n\n // Cross-tab synchronization via storage event\n useEffect(() => {\n if (!isClient || !syncTabs) {\n return;\n }\n\n const handleStorageChange = (event: StorageEvent) => {\n if (event.key !== key) {\n return;\n }\n\n if (event.newValue !== null) {\n try {\n setStoredValue(deserializerRef.current(event.newValue));\n } catch {\n // If parsing fails, reset to initial value\n setStoredValue(resolveInitialValue(initialValueRef.current));\n }\n } else {\n // Key was removed in another tab\n setStoredValue(resolveInitialValue(initialValueRef.current));\n }\n };\n\n window.addEventListener(\"storage\", handleStorageChange);\n return () => window.removeEventListener(\"storage\", handleStorageChange);\n }, [key, syncTabs, isClient]);\n\n // Re-read value when key changes\n useEffect(() => {\n if (!isClient) {\n return;\n }\n\n try {\n const item = window.localStorage.getItem(key);\n if (item !== null) {\n setStoredValue(deserializerRef.current(item));\n } else {\n setStoredValue(resolveInitialValue(initialValueRef.current));\n }\n } catch {\n setStoredValue(resolveInitialValue(initialValueRef.current));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key]);\n\n return [storedValue, setValue, removeValue] as const;\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/useLocalStorage.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\r\n\r\n/**\r\n * Type for initial value that can be a value or a function returning a value (lazy initialization)\r\n */\r\nexport type InitialValue<T> = T | (() => T);\r\n\r\n/**\r\n * Options for useLocalStorage hook\r\n */\r\nexport interface UseLocalStorageOptions<T> {\r\n /**\r\n * Custom serializer function for converting value to string\r\n * @default JSON.stringify\r\n */\r\n serializer?: (value: T) => string;\r\n /**\r\n * Custom deserializer function for parsing stored string to value\r\n * @default JSON.parse\r\n */\r\n deserializer?: (value: string) => T;\r\n /**\r\n * Whether to sync value across browser tabs via storage event\r\n * @default true\r\n */\r\n syncTabs?: boolean;\r\n /**\r\n * Callback function called when an error occurs\r\n */\r\n onError?: (error: Error) => void;\r\n}\r\n\r\n/**\r\n * Return type for useLocalStorage hook - tuple similar to useState\r\n */\r\nexport type UseLocalStorageReturn<T> = readonly [\r\n /** Current stored value */\r\n T,\r\n /** Function to update the value (same signature as useState setter) */\r\n React.Dispatch<React.SetStateAction<T>>,\r\n /** Function to remove the value from localStorage */\r\n () => void\r\n];\r\n\r\n/**\r\n * Helper function to resolve initial value (supports lazy initialization)\r\n */\r\nfunction resolveInitialValue<T>(initialValue: InitialValue<T>): T {\r\n return typeof initialValue === \"function\"\r\n ? (initialValue as () => T)()\r\n : initialValue;\r\n}\r\n\r\n/**\r\n * A hook for persisting state in localStorage with automatic synchronization.\r\n * Works like useState but persists the value in localStorage.\r\n *\r\n * @template T - The type of the stored value\r\n * @param key - The localStorage key to store the value under\r\n * @param initialValue - Initial value or function returning initial value (lazy initialization)\r\n * @param options - Configuration options for serialization, sync, and error handling\r\n * @returns A tuple of [storedValue, setValue, removeValue]\r\n *\r\n * @example\r\n * ```tsx\r\n * // Basic usage with string\r\n * function ThemeToggle() {\r\n * const [theme, setTheme, removeTheme] = useLocalStorage('theme', 'light');\r\n *\r\n * return (\r\n * <div>\r\n * <p>Current theme: {theme}</p>\r\n * <button onClick={() => setTheme('dark')}>Dark</button>\r\n * <button onClick={() => setTheme('light')}>Light</button>\r\n * <button onClick={removeTheme}>Reset</button>\r\n * </div>\r\n * );\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // With object type\r\n * interface UserSettings {\r\n * notifications: boolean;\r\n * language: string;\r\n * }\r\n *\r\n * const [settings, setSettings] = useLocalStorage<UserSettings>('settings', {\r\n * notifications: true,\r\n * language: 'en',\r\n * });\r\n *\r\n * // Functional update\r\n * setSettings(prev => ({ ...prev, notifications: false }));\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // With lazy initialization\r\n * const [config, setConfig] = useLocalStorage('config', () => computeExpensiveDefault());\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // With custom serializer/deserializer\r\n * const [date, setDate] = useLocalStorage<Date>('lastVisit', new Date(), {\r\n * serializer: (d) => d.toISOString(),\r\n * deserializer: (s) => new Date(s),\r\n * });\r\n * ```\r\n *\r\n * @example\r\n * ```tsx\r\n * // With error handling\r\n * const [value, setValue] = useLocalStorage('key', 'default', {\r\n * onError: (error) => console.error('Storage error:', error),\r\n * });\r\n * ```\r\n */\r\nexport function useLocalStorage<T>(\r\n key: string,\r\n initialValue: InitialValue<T>,\r\n options: UseLocalStorageOptions<T> = {}\r\n): UseLocalStorageReturn<T> {\r\n const {\r\n serializer = JSON.stringify,\r\n deserializer = JSON.parse,\r\n syncTabs = true,\r\n onError,\r\n } = options;\r\n\r\n // Store options in refs for stable references and access to latest values\r\n const serializerRef = useRef(serializer);\r\n const deserializerRef = useRef(deserializer);\r\n const onErrorRef = useRef(onError);\r\n serializerRef.current = serializer;\r\n deserializerRef.current = deserializer;\r\n onErrorRef.current = onError;\r\n\r\n // Store initialValue in ref for use in removeValue and storage event handler\r\n const initialValueRef = useRef(initialValue);\r\n initialValueRef.current = initialValue;\r\n\r\n // SSR check - check once at module level for consistency\r\n const isClient = typeof window !== \"undefined\";\r\n\r\n // Lazy initialization with localStorage read\r\n const [storedValue, setStoredValue] = useState<T>(() => {\r\n if (!isClient) {\r\n return resolveInitialValue(initialValue);\r\n }\r\n\r\n try {\r\n const item = window.localStorage.getItem(key);\r\n if (item !== null) {\r\n return deserializerRef.current(item);\r\n }\r\n return resolveInitialValue(initialValue);\r\n } catch (error) {\r\n onErrorRef.current?.(error as Error);\r\n return resolveInitialValue(initialValue);\r\n }\r\n });\r\n\r\n // Store current value in ref for stable setValue reference\r\n const storedValueRef = useRef<T>(storedValue);\r\n storedValueRef.current = storedValue;\r\n\r\n // setValue - stable reference (only depends on key)\r\n const setValue = useCallback<React.Dispatch<React.SetStateAction<T>>>(\r\n (value) => {\r\n try {\r\n const currentValue = storedValueRef.current;\r\n const valueToStore =\r\n value instanceof Function ? value(currentValue) : value;\r\n\r\n setStoredValue(valueToStore);\r\n\r\n if (typeof window !== \"undefined\") {\r\n window.localStorage.setItem(\r\n key,\r\n serializerRef.current(valueToStore)\r\n );\r\n }\r\n } catch (error) {\r\n onErrorRef.current?.(error as Error);\r\n }\r\n },\r\n [key]\r\n );\r\n\r\n // removeValue - stable reference\r\n const removeValue = useCallback(() => {\r\n try {\r\n const initial = resolveInitialValue(initialValueRef.current);\r\n setStoredValue(initial);\r\n\r\n if (typeof window !== \"undefined\") {\r\n window.localStorage.removeItem(key);\r\n }\r\n } catch (error) {\r\n onErrorRef.current?.(error as Error);\r\n }\r\n }, [key]);\r\n\r\n // Cross-tab synchronization via storage event\r\n useEffect(() => {\r\n if (!isClient || !syncTabs) {\r\n return;\r\n }\r\n\r\n const handleStorageChange = (event: StorageEvent) => {\r\n if (event.key !== key) {\r\n return;\r\n }\r\n\r\n if (event.newValue !== null) {\r\n try {\r\n setStoredValue(deserializerRef.current(event.newValue));\r\n } catch {\r\n // If parsing fails, reset to initial value\r\n setStoredValue(resolveInitialValue(initialValueRef.current));\r\n }\r\n } else {\r\n // Key was removed in another tab\r\n setStoredValue(resolveInitialValue(initialValueRef.current));\r\n }\r\n };\r\n\r\n window.addEventListener(\"storage\", handleStorageChange);\r\n return () => window.removeEventListener(\"storage\", handleStorageChange);\r\n }, [key, syncTabs, isClient]);\r\n\r\n // Re-read value when key changes\r\n useEffect(() => {\r\n if (!isClient) {\r\n return;\r\n }\r\n\r\n try {\r\n const item = window.localStorage.getItem(key);\r\n if (item !== null) {\r\n setStoredValue(deserializerRef.current(item));\r\n } else {\r\n setStoredValue(resolveInitialValue(initialValueRef.current));\r\n }\r\n } catch {\r\n setStoredValue(resolveInitialValue(initialValueRef.current));\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [key]);\r\n\r\n return [storedValue, setValue, removeValue] as const;\r\n}\r\n"],"mappings":";AAAA,SAAS,aAAa,WAAW,QAAQ,gBAAgB;AA+CzD,SAAS,oBAAuB,cAAkC;AAChE,SAAO,OAAO,iBAAiB,aAC1B,aAAyB,IAC1B;AACN;AAqEO,SAAS,gBACd,KACA,cACA,UAAqC,CAAC,GACZ;AAC1B,QAAM;AAAA,IACJ,aAAa,KAAK;AAAA,IAClB,eAAe,KAAK;AAAA,IACpB,WAAW;AAAA,IACX;AAAA,EACF,IAAI;AAGJ,QAAM,gBAAgB,OAAO,UAAU;AACvC,QAAM,kBAAkB,OAAO,YAAY;AAC3C,QAAM,aAAa,OAAO,OAAO;AACjC,gBAAc,UAAU;AACxB,kBAAgB,UAAU;AAC1B,aAAW,UAAU;AAGrB,QAAM,kBAAkB,OAAO,YAAY;AAC3C,kBAAgB,UAAU;AAG1B,QAAM,WAAW,OAAO,WAAW;AAGnC,QAAM,CAAC,aAAa,cAAc,IAAI,SAAY,MAAM;AACtD,QAAI,CAAC,UAAU;AACb,aAAO,oBAAoB,YAAY;AAAA,IACzC;AAEA,QAAI;AACF,YAAM,OAAO,OAAO,aAAa,QAAQ,GAAG;AAC5C,UAAI,SAAS,MAAM;AACjB,eAAO,gBAAgB,QAAQ,IAAI;AAAA,MACrC;AACA,aAAO,oBAAoB,YAAY;AAAA,IACzC,SAAS,OAAO;AACd,iBAAW,UAAU,KAAc;AACnC,aAAO,oBAAoB,YAAY;AAAA,IACzC;AAAA,EACF,CAAC;AAGD,QAAM,iBAAiB,OAAU,WAAW;AAC5C,iBAAe,UAAU;AAGzB,QAAM,WAAW;AAAA,IACf,CAAC,UAAU;AACT,UAAI;AACF,cAAM,eAAe,eAAe;AACpC,cAAM,eACJ,iBAAiB,WAAW,MAAM,YAAY,IAAI;AAEpD,uBAAe,YAAY;AAE3B,YAAI,OAAO,WAAW,aAAa;AACjC,iBAAO,aAAa;AAAA,YAClB;AAAA,YACA,cAAc,QAAQ,YAAY;AAAA,UACpC;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,mBAAW,UAAU,KAAc;AAAA,MACrC;AAAA,IACF;AAAA,IACA,CAAC,GAAG;AAAA,EACN;AAGA,QAAM,cAAc,YAAY,MAAM;AACpC,QAAI;AACF,YAAM,UAAU,oBAAoB,gBAAgB,OAAO;AAC3D,qBAAe,OAAO;AAEtB,UAAI,OAAO,WAAW,aAAa;AACjC,eAAO,aAAa,WAAW,GAAG;AAAA,MACpC;AAAA,IACF,SAAS,OAAO;AACd,iBAAW,UAAU,KAAc;AAAA,IACrC;AAAA,EACF,GAAG,CAAC,GAAG,CAAC;AAGR,YAAU,MAAM;AACd,QAAI,CAAC,YAAY,CAAC,UAAU;AAC1B;AAAA,IACF;AAEA,UAAM,sBAAsB,CAAC,UAAwB;AACnD,UAAI,MAAM,QAAQ,KAAK;AACrB;AAAA,MACF;AAEA,UAAI,MAAM,aAAa,MAAM;AAC3B,YAAI;AACF,yBAAe,gBAAgB,QAAQ,MAAM,QAAQ,CAAC;AAAA,QACxD,QAAQ;AAEN,yBAAe,oBAAoB,gBAAgB,OAAO,CAAC;AAAA,QAC7D;AAAA,MACF,OAAO;AAEL,uBAAe,oBAAoB,gBAAgB,OAAO,CAAC;AAAA,MAC7D;AAAA,IACF;AAEA,WAAO,iBAAiB,WAAW,mBAAmB;AACtD,WAAO,MAAM,OAAO,oBAAoB,WAAW,mBAAmB;AAAA,EACxE,GAAG,CAAC,KAAK,UAAU,QAAQ,CAAC;AAG5B,YAAU,MAAM;AACd,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AAEA,QAAI;AACF,YAAM,OAAO,OAAO,aAAa,QAAQ,GAAG;AAC5C,UAAI,SAAS,MAAM;AACjB,uBAAe,gBAAgB,QAAQ,IAAI,CAAC;AAAA,MAC9C,OAAO;AACL,uBAAe,oBAAoB,gBAAgB,OAAO,CAAC;AAAA,MAC7D;AAAA,IACF,QAAQ;AACN,qBAAe,oBAAoB,gBAAgB,OAAO,CAAC;AAAA,IAC7D;AAAA,EAEF,GAAG,CAAC,GAAG,CAAC;AAER,SAAO,CAAC,aAAa,UAAU,WAAW;AAC5C;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/useLocalStorage.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\n\n/**\n * Type for initial value that can be a value or a function returning a value (lazy initialization)\n */\nexport type InitialValue<T> = T | (() => T);\n\n/**\n * Options for useLocalStorage hook\n */\nexport interface UseLocalStorageOptions<T> {\n /**\n * Custom serializer function for converting value to string\n * @default JSON.stringify\n */\n serializer?: (value: T) => string;\n /**\n * Custom deserializer function for parsing stored string to value\n * @default JSON.parse\n */\n deserializer?: (value: string) => T;\n /**\n * Whether to sync value across browser tabs via storage event\n * @default true\n */\n syncTabs?: boolean;\n /**\n * Callback function called when an error occurs\n */\n onError?: (error: Error) => void;\n}\n\n/**\n * Return type for useLocalStorage hook - tuple similar to useState\n */\nexport type UseLocalStorageReturn<T> = readonly [\n /** Current stored value */\n T,\n /** Function to update the value (same signature as useState setter) */\n React.Dispatch<React.SetStateAction<T>>,\n /** Function to remove the value from localStorage */\n () => void\n];\n\n/**\n * Helper function to resolve initial value (supports lazy initialization)\n */\nfunction resolveInitialValue<T>(initialValue: InitialValue<T>): T {\n return typeof initialValue === \"function\"\n ? (initialValue as () => T)()\n : initialValue;\n}\n\n/**\n * A hook for persisting state in localStorage with automatic synchronization.\n * Works like useState but persists the value in localStorage.\n *\n * @template T - The type of the stored value\n * @param key - The localStorage key to store the value under\n * @param initialValue - Initial value or function returning initial value (lazy initialization)\n * @param options - Configuration options for serialization, sync, and error handling\n * @returns A tuple of [storedValue, setValue, removeValue]\n *\n * @example\n * ```tsx\n * // Basic usage with string\n * function ThemeToggle() {\n * const [theme, setTheme, removeTheme] = useLocalStorage('theme', 'light');\n *\n * return (\n * <div>\n * <p>Current theme: {theme}</p>\n * <button onClick={() => setTheme('dark')}>Dark</button>\n * <button onClick={() => setTheme('light')}>Light</button>\n * <button onClick={removeTheme}>Reset</button>\n * </div>\n * );\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With object type\n * interface UserSettings {\n * notifications: boolean;\n * language: string;\n * }\n *\n * const [settings, setSettings] = useLocalStorage<UserSettings>('settings', {\n * notifications: true,\n * language: 'en',\n * });\n *\n * // Functional update\n * setSettings(prev => ({ ...prev, notifications: false }));\n * ```\n *\n * @example\n * ```tsx\n * // With lazy initialization\n * const [config, setConfig] = useLocalStorage('config', () => computeExpensiveDefault());\n * ```\n *\n * @example\n * ```tsx\n * // With custom serializer/deserializer\n * const [date, setDate] = useLocalStorage<Date>('lastVisit', new Date(), {\n * serializer: (d) => d.toISOString(),\n * deserializer: (s) => new Date(s),\n * });\n * ```\n *\n * @example\n * ```tsx\n * // With error handling\n * const [value, setValue] = useLocalStorage('key', 'default', {\n * onError: (error) => console.error('Storage error:', error),\n * });\n * ```\n */\nexport function useLocalStorage<T>(\n key: string,\n initialValue: InitialValue<T>,\n options: UseLocalStorageOptions<T> = {}\n): UseLocalStorageReturn<T> {\n const {\n serializer = JSON.stringify,\n deserializer = JSON.parse,\n syncTabs = true,\n onError,\n } = options;\n\n // Store options in refs for stable references and access to latest values\n const serializerRef = useRef(serializer);\n const deserializerRef = useRef(deserializer);\n const onErrorRef = useRef(onError);\n serializerRef.current = serializer;\n deserializerRef.current = deserializer;\n onErrorRef.current = onError;\n\n // Store initialValue in ref for use in removeValue and storage event handler\n const initialValueRef = useRef(initialValue);\n initialValueRef.current = initialValue;\n\n // SSR check - check once at module level for consistency\n const isClient = typeof window !== \"undefined\";\n\n // Lazy initialization with localStorage read\n const [storedValue, setStoredValue] = useState<T>(() => {\n if (!isClient) {\n return resolveInitialValue(initialValue);\n }\n\n try {\n const item = window.localStorage.getItem(key);\n if (item !== null) {\n return deserializerRef.current(item);\n }\n return resolveInitialValue(initialValue);\n } catch (error) {\n onErrorRef.current?.(error as Error);\n return resolveInitialValue(initialValue);\n }\n });\n\n // Store current value in ref for stable setValue reference\n const storedValueRef = useRef<T>(storedValue);\n storedValueRef.current = storedValue;\n\n // setValue - stable reference (only depends on key)\n const setValue = useCallback<React.Dispatch<React.SetStateAction<T>>>(\n (value) => {\n try {\n const currentValue = storedValueRef.current;\n const valueToStore =\n value instanceof Function ? value(currentValue) : value;\n\n setStoredValue(valueToStore);\n\n if (typeof window !== \"undefined\") {\n window.localStorage.setItem(\n key,\n serializerRef.current(valueToStore)\n );\n }\n } catch (error) {\n onErrorRef.current?.(error as Error);\n }\n },\n [key]\n );\n\n // removeValue - stable reference\n const removeValue = useCallback(() => {\n try {\n const initial = resolveInitialValue(initialValueRef.current);\n setStoredValue(initial);\n\n if (typeof window !== \"undefined\") {\n window.localStorage.removeItem(key);\n }\n } catch (error) {\n onErrorRef.current?.(error as Error);\n }\n }, [key]);\n\n // Cross-tab synchronization via storage event\n useEffect(() => {\n if (!isClient || !syncTabs) {\n return;\n }\n\n const handleStorageChange = (event: StorageEvent) => {\n if (event.key !== key) {\n return;\n }\n\n if (event.newValue !== null) {\n try {\n setStoredValue(deserializerRef.current(event.newValue));\n } catch {\n // If parsing fails, reset to initial value\n setStoredValue(resolveInitialValue(initialValueRef.current));\n }\n } else {\n // Key was removed in another tab\n setStoredValue(resolveInitialValue(initialValueRef.current));\n }\n };\n\n window.addEventListener(\"storage\", handleStorageChange);\n return () => window.removeEventListener(\"storage\", handleStorageChange);\n }, [key, syncTabs, isClient]);\n\n // Re-read value when key changes\n useEffect(() => {\n if (!isClient) {\n return;\n }\n\n try {\n const item = window.localStorage.getItem(key);\n if (item !== null) {\n setStoredValue(deserializerRef.current(item));\n } else {\n setStoredValue(resolveInitialValue(initialValueRef.current));\n }\n } catch {\n setStoredValue(resolveInitialValue(initialValueRef.current));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key]);\n\n return [storedValue, setValue, removeValue] as const;\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED