ohif-viewer/platform/ui-next/src/hooks/useSessionStorage.tsx
2025-05-02 14:05:40 -04:00

72 lines
2.2 KiB
TypeScript

import { useState, useEffect, useCallback } from 'react';
/**
* A map of session storage items that should be cleared out of session storage
* when the page unloads.
*/
const sessionItemsToClearOnUnload: Map<string, string> = new Map<string, string>();
/**
* This callback simulates clearing the various session items when a page unloads.
* When the page is hidden the session storage items are removed but maintained
* in the map above in case the page becomes visible again. So those pages that
* are hidden because they are being unloaded have their session storage disposed
* of for ever. For those pages that are hidden, but later return to visible,
* this callback restores the session storage from the map above.
*/
const visibilityChangeCallback = () => {
if (document.visibilityState === 'hidden') {
Array.from(sessionItemsToClearOnUnload.keys()).forEach(key => {
window.sessionStorage.removeItem(key);
});
} else {
Array.from(sessionItemsToClearOnUnload.keys()).forEach(key => {
window.sessionStorage.setItem(key, sessionItemsToClearOnUnload.get(key));
});
}
};
/**
* Technically there is no memory leak here because the listener needs to
* persist until the page unloads and once the page unloads it will be gone.
*/
document.addEventListener('visibilitychange', visibilityChangeCallback);
type useSessionStorageProps = {
key: string;
defaultValue: unknown;
clearOnUnload: boolean;
};
const useSessionStorage = ({
key,
defaultValue = {},
clearOnUnload = false,
}: useSessionStorageProps) => {
const valueFromStorage = window.sessionStorage.getItem(key);
const storageValue = valueFromStorage ? JSON.parse(valueFromStorage) : defaultValue;
const [sessionItem, setSessionItem] = useState({ ...storageValue });
const updateSessionItem = useCallback(value => {
setSessionItem({ ...value });
const valueAsStr = JSON.stringify(value);
if (!clearOnUnload || document.visibilityState === 'visible') {
window.sessionStorage.setItem(key, valueAsStr);
}
if (clearOnUnload) {
sessionItemsToClearOnUnload.set(key, valueAsStr);
}
}, []);
useEffect(() => {
updateSessionItem(sessionItem);
}, []);
return [sessionItem, updateSessionItem];
};
export default useSessionStorage;