UNPKG

bananas-commerce-admin

Version:

What's this, an admin for apes?

78 lines (67 loc) 2.48 kB
import { useEffect, useState } from "react"; /** * The `useStorage` hook is a generic hook for reactively storing state in a * similar fashion to reacts usual {@link useState} hook. There is however some * caveats which are good to keep in mind: * - Any value of type `T` needs to be JSON (de-)serializeable. That means * storing certain non-serializeable values can result in unexpected * behavior, for example storing `Date` objects will stringify them. * - Setting the value to `undefined` is equivalent to deleting the storage * entry, not storing an `undefined` value. The reasoning behind this is * that because JSON doesn't support `undefined` it should instead indicate * an `undefined` value. * - The hook is designed to listen to the global `storage` event which * should make state changes propagate within the same context. If the * storage is for example modified from another tab that change should * trigger a state update in the current tab too. The behaviour of this may * be browser dependant. */ export function useStorage<T>( storage: Storage, key: string, initial: T, ): [T, React.Dispatch<React.SetStateAction<T>>] { const stored = storage.getItem(key); const value = stored === null ? initial : JSON.parse(stored); const [state, setState] = useState(value); useEffect(() => { if (state === undefined) { storage.removeItem(key); } else { storage.setItem(key, JSON.stringify(state)); } }, [state]); useEffect(() => { const listener = (event: StorageEvent) => { if (event.storageArea !== storage) { return; } if (event.key === null) { setState(initial); return; } if (event.key === key && event.newValue !== event.oldValue && event.newValue !== state) { setState(event.newValue !== null ? JSON.parse(event.newValue) : null); } }; addEventListener("storage", listener); return () => removeEventListener("storage", listener); }, [storage]); return [state, setState]; } /** * A hook for storing react state in `localStorage`. * * @see useStorage */ export function useLocalStorage<T>(key: string, initial: T) { return useStorage(localStorage, key, initial); } /** * A hook for storing react state in `sessionStorage`. * * @see useStorage */ export function useSessionStorage<T>(key: string, initial?: T) { return useStorage(sessionStorage, key, initial); }