44 lines
1.2 KiB
TypeScript
44 lines
1.2 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
|
|
import { LocalStorageKey } from '@/constants/localStorage';
|
|
|
|
import { getLocalStorage, setLocalStorage } from '@/lib/localStorage';
|
|
import { log } from '@/lib/telemetry';
|
|
|
|
export const useLocalStorage = <Value>({
|
|
key,
|
|
defaultValue,
|
|
validateFn,
|
|
}: {
|
|
key: LocalStorageKey;
|
|
defaultValue: Value;
|
|
validateFn?: (value: Value) => boolean;
|
|
}) => {
|
|
const [value, setValue] = useState(getLocalStorage({ key, defaultValue, validateFn }));
|
|
|
|
// Sync localStorage values across parallel browser sessions
|
|
useEffect(() => {
|
|
const onStorage = (e: StorageEvent) => {
|
|
if (key === e.key) {
|
|
try {
|
|
const newValue = e.newValue ? (JSON.parse(e.newValue) as Value) : undefined;
|
|
if (newValue !== undefined) setValue(newValue);
|
|
} catch (error) {
|
|
log('useLocalStorage/onStorage', error);
|
|
return false;
|
|
}
|
|
}
|
|
};
|
|
|
|
globalThis.window.addEventListener('storage', onStorage);
|
|
|
|
return () => globalThis.window.removeEventListener('storage', onStorage);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
setLocalStorage({ key, value });
|
|
}, [value]);
|
|
|
|
return [value, setValue] as const;
|
|
};
|