import { observable, autorun, set, toJS, runInAction } from "mobx"; interface LocalStoreResult { value: T; destroy: () => void; } function localStored( key: string, defaultValue: T, ): LocalStoreResult { const initial: T = { ...defaultValue }; const fromStorage = localStorage.getItem(key); if (fromStorage) { try { Object.assign(initial, JSON.parse(fromStorage)); } catch { // ignore malformed JSON, use defaults } } const obsVal = observable(initial); const disposeAutorun = autorun( () => { localStorage.setItem(key, JSON.stringify(toJS(obsVal))); }, { delay: 0 }, ); const onStorageEvent = (e: StorageEvent) => { if (e.key === key && e.newValue) { try { runInAction(() => set(obsVal, JSON.parse(e.newValue!))); } catch { // ignore malformed JSON from other tabs } } }; window.addEventListener("storage", onStorageEvent); return { value: obsVal, destroy() { disposeAutorun(); window.removeEventListener("storage", onStorageEvent); }, }; } export { localStored };