@mantine/hooks
Version:
A collection of 50+ hooks for state and UI management
1 lines • 8.77 kB
Source Map (JSON)
{"version":3,"file":"create-storage.mjs","names":[],"sources":["../../src/use-local-storage/create-storage.ts"],"sourcesContent":["/* oxlint-disable no-console */\nimport { useCallback, useEffect, useState } from 'react';\nimport { useWindowEvent } from '../use-window-event/use-window-event';\n\nexport type StorageType = 'localStorage' | 'sessionStorage';\n\nexport interface UseStorageOptions<T> {\n /** Storage key */\n key: string;\n\n /** Default value that will be set if value is not found in storage */\n defaultValue?: T;\n\n /** If set to true, value will be updated in useEffect after mount. Default value is true. */\n getInitialValueInEffect?: boolean;\n\n /** Determines whether the value must be synced between browser tabs, `true` by default */\n sync?: boolean;\n\n /** Function to serialize value into string to be save in storage */\n serialize?: (value: T) => string;\n\n /** Function to deserialize string value from storage to value */\n deserialize?: (value: string | undefined) => T;\n}\n\nfunction serializeJSON<T>(value: T, hookName: string = 'use-local-storage') {\n try {\n return JSON.stringify(value);\n } catch (error) {\n throw new Error(`@mantine/hooks ${hookName}: Failed to serialize the value`);\n }\n}\n\nfunction deserializeJSON(value: string | undefined) {\n try {\n return value && JSON.parse(value);\n } catch {\n return value;\n }\n}\n\nfunction createStorageHandler(type: StorageType) {\n const getItem = (key: string) => {\n try {\n return window[type].getItem(key);\n } catch (error) {\n console.warn('use-local-storage: Failed to get value from storage, localStorage is blocked');\n return null;\n }\n };\n\n const setItem = (key: string, value: string) => {\n try {\n window[type].setItem(key, value);\n } catch (error) {\n console.warn('use-local-storage: Failed to set value to storage, localStorage is blocked');\n }\n };\n\n const removeItem = (key: string) => {\n try {\n window[type].removeItem(key);\n } catch (error) {\n console.warn(\n 'use-local-storage: Failed to remove value from storage, localStorage is blocked'\n );\n }\n };\n\n return { getItem, setItem, removeItem };\n}\n\nexport type UseStorageReturnValue<T> = [\n T, // current value\n (val: T | ((prevState: T) => T)) => void, // callback to set value in storage\n () => void, // callback to remove value from storage\n];\n\nexport function createStorage<T>(type: StorageType, hookName: string) {\n const eventName = type === 'localStorage' ? 'mantine-local-storage' : 'mantine-session-storage';\n const { getItem, setItem, removeItem } = createStorageHandler(type);\n\n return function useStorage({\n key,\n defaultValue,\n getInitialValueInEffect = true,\n sync = true,\n deserialize = deserializeJSON,\n serialize = (value: T) => serializeJSON(value, hookName),\n }: UseStorageOptions<T>): UseStorageReturnValue<T> {\n const readStorageValue = useCallback(\n (skipStorage?: boolean): T => {\n let storageBlockedOrSkipped;\n\n try {\n storageBlockedOrSkipped =\n typeof window === 'undefined' ||\n !(type in window) ||\n window[type] === null ||\n !!skipStorage;\n } catch (_e) {\n storageBlockedOrSkipped = true;\n }\n\n if (storageBlockedOrSkipped) {\n return defaultValue as T;\n }\n\n const storageValue = getItem(key);\n return storageValue !== null ? deserialize(storageValue) : (defaultValue as T);\n },\n [key, defaultValue]\n );\n\n const [value, setValue] = useState<T>(readStorageValue(getInitialValueInEffect));\n\n const setStorageValue = useCallback(\n (val: T | ((prevState: T) => T)) => {\n if (val instanceof Function) {\n setValue((current) => {\n const result = val(current);\n setItem(key, serialize(result));\n // Defer dispatching this event to avoid the handler being called during render.\n queueMicrotask(() => {\n window.dispatchEvent(new CustomEvent(eventName, { detail: { key, value: result } }));\n });\n return result;\n });\n } else {\n setItem(key, serialize(val));\n window.dispatchEvent(new CustomEvent(eventName, { detail: { key, value: val } }));\n setValue(val);\n }\n },\n [key]\n );\n\n const removeStorageValue = useCallback(() => {\n removeItem(key);\n setValue(defaultValue as T);\n window.dispatchEvent(new CustomEvent(eventName, { detail: { key, value: defaultValue } }));\n }, [key, defaultValue]);\n\n useWindowEvent('storage', (event) => {\n if (sync) {\n if (event.storageArea === window[type] && event.key === key) {\n setValue(deserialize(event.newValue ?? undefined));\n }\n }\n });\n\n useWindowEvent(eventName, (event) => {\n if (sync) {\n if (event.detail.key === key) {\n setValue(event.detail.value);\n }\n }\n });\n\n useEffect(() => {\n if (defaultValue !== undefined && value === undefined) {\n setStorageValue(defaultValue);\n }\n }, [defaultValue, value, setStorageValue]);\n\n useEffect(() => {\n const val = readStorageValue();\n val !== undefined && setStorageValue(val);\n }, [key]);\n\n return [value === undefined ? (defaultValue as T) : value, setStorageValue, removeStorageValue];\n };\n}\n\nexport function readValue(type: StorageType) {\n const { getItem } = createStorageHandler(type);\n\n return function read<T>({\n key,\n defaultValue,\n deserialize = deserializeJSON,\n }: UseStorageOptions<T>) {\n let storageBlockedOrSkipped;\n\n try {\n storageBlockedOrSkipped =\n typeof window === 'undefined' || !(type in window) || window[type] === null;\n } catch (_e) {\n storageBlockedOrSkipped = true;\n }\n\n if (storageBlockedOrSkipped) {\n return defaultValue as T;\n }\n\n const storageValue = getItem(key);\n return storageValue !== null ? deserialize(storageValue) : (defaultValue as T);\n };\n}\n"],"mappings":"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"}