import {useCallback, useEffect} from 'react'; import {useLocalStorageState} from 'sentry/utils/useLocalStorageState'; type SyncedLocalStorageEvent = CustomEvent<{key: string; value: S}>; const SYNCED_STORAGE_EVENT = 'synced-local-storage'; function isCustomEvent(event: Event): event is CustomEvent { return 'detail' in event; } function isSyncedLocalStorageEvent( event: Event, key: string ): event is SyncedLocalStorageEvent { return ( isCustomEvent(event) && event.type === SYNCED_STORAGE_EVENT && event.detail.key === key ); } /** * Same as `useLocalStorageState`, but notifies and reacts to state changes. * Use this you want to access local storage state from multiple components * on the same page. */ export function useSyncedLocalStorageState( key: string, initialState: S | ((value?: unknown, rawValue?: unknown) => S) ): [S, (value: S) => void] { const [value, setValue] = useLocalStorageState(key, initialState); const setValueAndNotify = useCallback( newValue => { setValue(newValue); // We use a custom event to notify all consumers of this hook window.dispatchEvent( new CustomEvent(SYNCED_STORAGE_EVENT, {detail: {key, value: newValue}}) ); }, [key, setValue] ); useEffect(() => { const handleNewSyncedLocalStorageEvent = (event: Event) => { if (isSyncedLocalStorageEvent(event, key)) { setValue(event.detail.value); } }; window.addEventListener(SYNCED_STORAGE_EVENT, handleNewSyncedLocalStorageEvent); return () => { window.removeEventListener(SYNCED_STORAGE_EVENT, handleNewSyncedLocalStorageEvent); }; }, [key, setValue, value]); return [value, setValueAndNotify]; }