mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
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];
|
|
}
|