1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- import {useCallback, useEffect} from 'react';
- import {useLocalStorageState} from 'sentry/utils/useLocalStorageState';
- type SyncedLocalStorageEvent<S> = 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<S>(
- event: Event,
- key: string
- ): event is SyncedLocalStorageEvent<S> {
- 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<S>(
- 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<S>(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];
- }
|