rooks
Version:
Essential React custom hooks ⚓ to super charge your components!
142 lines (141 loc) • 5.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useSessionstorageState = void 0;
var react_1 = require("react");
function getValueFromSessionStorage(key) {
var _a;
if (typeof sessionStorage === "undefined") {
return null;
}
var storedValue = (_a = sessionStorage.getItem(key)) !== null && _a !== void 0 ? _a : "null";
try {
return JSON.parse(storedValue);
}
catch (error) {
console.error(error);
}
return storedValue;
}
function saveValueToSessionStorage(key, value) {
if (typeof sessionStorage === "undefined") {
return null;
}
return sessionStorage.setItem(key, JSON.stringify(value));
}
/**
* @param key Key of the sessionStorage object
* @param initialState Default initial value
*/
function initialize(key, initialState) {
var valueLoadedFromSessionStorage = getValueFromSessionStorage(key);
if (valueLoadedFromSessionStorage === null) {
return initialState;
}
else {
return valueLoadedFromSessionStorage;
}
}
/**
* useSessionstorageState hook
* Tracks a value within sessionStorage and updates it
*
* @param {string} key - Key of the sessionStorage object
* @param {any} initialState - Default initial value
* @returns {[any, Dispatch<SetStateAction<any>>, () => void]}
* @see https://react-hooks.org/docs/useSessionstorageState
*/
function useSessionstorageState(key, initialState) {
var _a = (0, react_1.useState)(function () { return initialize(key, initialState); }), value = _a[0], setValue = _a[1];
var isUpdateFromCrossDocumentListener = (0, react_1.useRef)(false);
var isUpdateFromWithinDocumentListener = (0, react_1.useRef)(false);
var customEventTypeName = (0, react_1.useMemo)(function () {
return "rooks-".concat(key, "-sessionstorage-update");
}, [key]);
(0, react_1.useEffect)(function () {
/**
* We need to ensure there is no loop of
* storage events fired. Hence we are using a ref
* to keep track of whether setValue is from another
* storage event
*/
if (!isUpdateFromCrossDocumentListener.current) {
saveValueToSessionStorage(key, value);
}
}, [key, value]);
var listenToCrossDocumentStorageEvents = (0, react_1.useCallback)(function (event) {
var _a;
if (event.storageArea === sessionStorage && event.key === key) {
try {
isUpdateFromCrossDocumentListener.current = true;
var newValue = JSON.parse((_a = event.newValue) !== null && _a !== void 0 ? _a : "null");
if (value !== newValue) {
setValue(newValue);
}
}
catch (error) {
console.log(error);
}
}
}, [key, value]);
// check for changes across windows
(0, react_1.useEffect)(function () {
// eslint-disable-next-line no-negated-condition
if (typeof window !== "undefined") {
window.addEventListener("storage", listenToCrossDocumentStorageEvents);
return function () {
window.removeEventListener("storage", listenToCrossDocumentStorageEvents);
};
}
else {
console.warn("[useSessionstorageState] window is undefined.");
return function () { };
}
}, [listenToCrossDocumentStorageEvents]);
var listenToCustomEventWithinDocument = (0, react_1.useCallback)(function (event) {
try {
isUpdateFromWithinDocumentListener.current = true;
var newValue = event.detail.newValue;
if (value !== newValue) {
setValue(newValue);
}
}
catch (error) {
console.log(error);
}
}, [value]);
// check for changes within document
(0, react_1.useEffect)(function () {
// eslint-disable-next-line no-negated-condition
if (typeof document !== "undefined") {
document.addEventListener(customEventTypeName, listenToCustomEventWithinDocument);
return function () {
document.removeEventListener(customEventTypeName, listenToCustomEventWithinDocument);
};
}
else {
console.warn("[useSessionstorageState] document is undefined.");
return function () { };
}
}, [customEventTypeName, listenToCustomEventWithinDocument]);
var broadcastValueWithinDocument = (0, react_1.useCallback)(function (newValue) {
// eslint-disable-next-line no-negated-condition
if (typeof document !== "undefined") {
var event_1 = new CustomEvent(customEventTypeName, { detail: { newValue: newValue } });
document.dispatchEvent(event_1);
}
else {
console.warn("[useSessionstorageState] document is undefined.");
}
}, [customEventTypeName]);
var set = (0, react_1.useCallback)(function (newValue) {
isUpdateFromCrossDocumentListener.current = false;
isUpdateFromWithinDocumentListener.current = false;
setValue(newValue);
broadcastValueWithinDocument(newValue);
}, [broadcastValueWithinDocument]);
var remove = (0, react_1.useCallback)(function () {
sessionStorage.removeItem(key);
}, [key]);
return [value, set, remove];
}
exports.useSessionstorageState = useSessionstorageState;