use-session-storage-state
Advanced tools
Comparing version 18.1.1 to 18.2.0
@@ -1,10 +0,10 @@ | ||
import { useRef, useMemo, useEffect, useCallback, useSyncExternalStore } from 'react'; | ||
import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'; | ||
// in memory fallback used then `sessionStorage` throws an error | ||
export const inMemoryData = new Map(); | ||
export default function useSessionStorageState(key, options) { | ||
const defaultValue = options === null || options === void 0 ? void 0 : options.defaultValue; | ||
const [defaultValue] = useState(options === null || options === void 0 ? void 0 : options.defaultValue); | ||
// SSR support | ||
// - on the server, return a constant value | ||
// - this makes the implementation simpler and smaller the `sessionStorage` object is `undefined` | ||
// on the server | ||
// - this makes the implementation simpler and smaller because the `sessionStorage` object is | ||
// `undefined` on the server | ||
if (typeof window === 'undefined') { | ||
@@ -27,3 +27,2 @@ return [ | ||
function useBrowserSessionStorageState(key, defaultValue, storageSync = true, parse = parseJSON, stringify = JSON.stringify) { | ||
const initialDefaultValue = useRef(defaultValue).current; | ||
// store default value in sessionStorage: | ||
@@ -35,4 +34,4 @@ // - initial issue: https://github.com/astoilkov/use-local-storage-state/issues/26 | ||
if (!inMemoryData.has(key) && | ||
initialDefaultValue !== undefined && | ||
sessionStorage.getItem(key) === null) { | ||
defaultValue !== undefined && | ||
goodTry(() => sessionStorage.getItem(key)) === null) { | ||
// reasons for `sessionStorage` to throw an error: | ||
@@ -44,6 +43,3 @@ // - maximum quota is exceeded | ||
// "SecurityError: The operation is insecure." | ||
try { | ||
sessionStorage.setItem(key, stringify(initialDefaultValue)); | ||
} | ||
catch (_a) { } | ||
goodTry(() => sessionStorage.setItem(key, stringify(defaultValue))); | ||
} | ||
@@ -53,3 +49,3 @@ // we keep the `parsed` value in a ref because `useSyncExternalStore` requires a cached version | ||
item: null, | ||
parsed: initialDefaultValue, | ||
parsed: defaultValue, | ||
}); | ||
@@ -69,3 +65,4 @@ const value = useSyncExternalStore(useCallback((onStoreChange) => { | ||
() => { | ||
const item = sessionStorage.getItem(key); | ||
var _a; | ||
const item = (_a = goodTry(() => sessionStorage.getItem(key))) !== null && _a !== void 0 ? _a : null; | ||
if (inMemoryData.has(key)) { | ||
@@ -80,6 +77,6 @@ storageValue.current = { | ||
try { | ||
parsed = item === null ? initialDefaultValue : parse(item); | ||
parsed = item === null ? defaultValue : parse(item); | ||
} | ||
catch (_a) { | ||
parsed = initialDefaultValue; | ||
catch (_b) { | ||
parsed = defaultValue; | ||
} | ||
@@ -94,3 +91,3 @@ storageValue.current = { | ||
// istanbul ignore next | ||
() => initialDefaultValue); | ||
() => defaultValue); | ||
const setState = useCallback((newValue) => { | ||
@@ -102,3 +99,3 @@ const value = newValue instanceof Function ? newValue(storageValue.current.parsed) : newValue; | ||
// `sessionStorage.setItem()` will throw | ||
// - trying to access sessionStorage object when cookies are disabled in Safari throws | ||
// - trying to access `sessionStorage` object when cookies are disabled in Safari throws | ||
// "SecurityError: The operation is insecure." | ||
@@ -122,3 +119,3 @@ try { | ||
const onStorage = (e) => { | ||
if (e.storageArea === sessionStorage && e.key === key) { | ||
if (e.storageArea === goodTry(() => sessionStorage) && e.key === key) { | ||
triggerCallbacks(key); | ||
@@ -134,10 +131,10 @@ } | ||
{ | ||
isPersistent: value === initialDefaultValue || !inMemoryData.has(key), | ||
isPersistent: value === defaultValue || !inMemoryData.has(key), | ||
removeItem() { | ||
goodTry(() => sessionStorage.removeItem(key)); | ||
inMemoryData.delete(key); | ||
sessionStorage.removeItem(key); | ||
triggerCallbacks(key); | ||
}, | ||
}, | ||
], [key, setState, value, initialDefaultValue]); | ||
], [key, setState, value, defaultValue]); | ||
} | ||
@@ -156,1 +153,9 @@ // notifies all instances using the same `key` to update | ||
} | ||
function goodTry(tryFn) { | ||
try { | ||
return tryFn(); | ||
} | ||
catch (_a) { | ||
return undefined; | ||
} | ||
} |
{ | ||
"name": "use-session-storage-state", | ||
"version": "18.1.1", | ||
"version": "18.2.0", | ||
"description": "React hook that persist data in sessionStorage", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -27,3 +27,3 @@ # `use-session-storage-state` | ||
- SSR support. | ||
- Handles the `Window` [`storage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event) event and updates changes across browser tabs, windows, and iframe's. Disable with `storageSync: false`. | ||
- Handles the `Window` [`storage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event) event and updates changes across iframe's. Disable with `storageSync: false`. | ||
- In-memory fallback when `sessionStorage` throws an error and can't store the data. Provides a `isPersistent` API to let you notify the user their data isn't currently being stored. | ||
@@ -176,4 +176,6 @@ - Aiming for high-quality with [my open-source principles](https://astoilkov.com/my-open-source-principles). | ||
Setting to `false` doesn't subscribe to the [Window storage event](https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event). If you set to `false`, updates won't be synchronized across tabs, windows and iframes. | ||
Setting to `false` doesn't subscribe to the [Window storage event](https://developer.mozilla.org/en-US/docs/Web/API/Window/storage_event). If you set to `false`, updates won't be synchronized across iframes. | ||
Note: Unlike `localStorage`, `sessionStorage` doesn't fire the `storage` event across tabs and windows. | ||
### `options.serializer` | ||
@@ -180,0 +182,0 @@ |
import type { Dispatch, SetStateAction } from 'react'; | ||
export declare const inMemoryData: Map<string, unknown>; | ||
export declare type SessionStorageOptions<T> = { | ||
defaultValue?: T; | ||
defaultValue?: T | (() => T); | ||
storageSync?: boolean; | ||
@@ -6,0 +6,0 @@ serializer?: { |
@@ -8,7 +8,7 @@ "use strict"; | ||
function useSessionStorageState(key, options) { | ||
const defaultValue = options === null || options === void 0 ? void 0 : options.defaultValue; | ||
const [defaultValue] = (0, react_1.useState)(options === null || options === void 0 ? void 0 : options.defaultValue); | ||
// SSR support | ||
// - on the server, return a constant value | ||
// - this makes the implementation simpler and smaller the `sessionStorage` object is `undefined` | ||
// on the server | ||
// - this makes the implementation simpler and smaller because the `sessionStorage` object is | ||
// `undefined` on the server | ||
if (typeof window === 'undefined') { | ||
@@ -32,3 +32,2 @@ return [ | ||
function useBrowserSessionStorageState(key, defaultValue, storageSync = true, parse = parseJSON, stringify = JSON.stringify) { | ||
const initialDefaultValue = (0, react_1.useRef)(defaultValue).current; | ||
// store default value in sessionStorage: | ||
@@ -40,4 +39,4 @@ // - initial issue: https://github.com/astoilkov/use-local-storage-state/issues/26 | ||
if (!exports.inMemoryData.has(key) && | ||
initialDefaultValue !== undefined && | ||
sessionStorage.getItem(key) === null) { | ||
defaultValue !== undefined && | ||
goodTry(() => sessionStorage.getItem(key)) === null) { | ||
// reasons for `sessionStorage` to throw an error: | ||
@@ -49,6 +48,3 @@ // - maximum quota is exceeded | ||
// "SecurityError: The operation is insecure." | ||
try { | ||
sessionStorage.setItem(key, stringify(initialDefaultValue)); | ||
} | ||
catch (_a) { } | ||
goodTry(() => sessionStorage.setItem(key, stringify(defaultValue))); | ||
} | ||
@@ -58,3 +54,3 @@ // we keep the `parsed` value in a ref because `useSyncExternalStore` requires a cached version | ||
item: null, | ||
parsed: initialDefaultValue, | ||
parsed: defaultValue, | ||
}); | ||
@@ -74,3 +70,4 @@ const value = (0, react_1.useSyncExternalStore)((0, react_1.useCallback)((onStoreChange) => { | ||
() => { | ||
const item = sessionStorage.getItem(key); | ||
var _a; | ||
const item = (_a = goodTry(() => sessionStorage.getItem(key))) !== null && _a !== void 0 ? _a : null; | ||
if (exports.inMemoryData.has(key)) { | ||
@@ -85,6 +82,6 @@ storageValue.current = { | ||
try { | ||
parsed = item === null ? initialDefaultValue : parse(item); | ||
parsed = item === null ? defaultValue : parse(item); | ||
} | ||
catch (_a) { | ||
parsed = initialDefaultValue; | ||
catch (_b) { | ||
parsed = defaultValue; | ||
} | ||
@@ -99,3 +96,3 @@ storageValue.current = { | ||
// istanbul ignore next | ||
() => initialDefaultValue); | ||
() => defaultValue); | ||
const setState = (0, react_1.useCallback)((newValue) => { | ||
@@ -107,3 +104,3 @@ const value = newValue instanceof Function ? newValue(storageValue.current.parsed) : newValue; | ||
// `sessionStorage.setItem()` will throw | ||
// - trying to access sessionStorage object when cookies are disabled in Safari throws | ||
// - trying to access `sessionStorage` object when cookies are disabled in Safari throws | ||
// "SecurityError: The operation is insecure." | ||
@@ -127,3 +124,3 @@ try { | ||
const onStorage = (e) => { | ||
if (e.storageArea === sessionStorage && e.key === key) { | ||
if (e.storageArea === goodTry(() => sessionStorage) && e.key === key) { | ||
triggerCallbacks(key); | ||
@@ -139,10 +136,10 @@ } | ||
{ | ||
isPersistent: value === initialDefaultValue || !exports.inMemoryData.has(key), | ||
isPersistent: value === defaultValue || !exports.inMemoryData.has(key), | ||
removeItem() { | ||
goodTry(() => sessionStorage.removeItem(key)); | ||
exports.inMemoryData.delete(key); | ||
sessionStorage.removeItem(key); | ||
triggerCallbacks(key); | ||
}, | ||
}, | ||
], [key, setState, value, initialDefaultValue]); | ||
], [key, setState, value, defaultValue]); | ||
} | ||
@@ -161,1 +158,9 @@ // notifies all instances using the same `key` to update | ||
} | ||
function goodTry(tryFn) { | ||
try { | ||
return tryFn(); | ||
} | ||
catch (_a) { | ||
return undefined; | ||
} | ||
} |
25202
338
190