Vue ref that lazily reads from localStorage
vue-localstorage-ref.ts edited
53 lines 1.1 kB view raw
1import { computed, shallowRef, triggerRef, type Ref } from "vue"; 2 3export const useLocalStorageRef = <T>( 4 key: string, 5 opts: { 6 broadcast?: boolean; 7 parse: (value: string | null) => T; 8 stringify: (value: T) => string | null; 9 } 10): Ref<T> => { 11 const [track, trigger] = useTrigger(); 12 13 const derivation = writable((): T => { 14 track(); 15 16 const raw = localStorage.getItem(key); 17 const value = opts.parse(raw); 18 19 return value; 20 }); 21 22 const store = computed({ 23 get(): T { 24 const value = derivation.value; 25 26 return value; 27 }, 28 set(next) { 29 const raw = opts.stringify(next); 30 31 derivation.value = next; 32 33 if (raw !== null) { 34 localStorage.setItem(key, raw); 35 } else { 36 localStorage.removeItem(key); 37 } 38 }, 39 }); 40 41 createEventListener(window, "storage", (ev) => { 42 if (ev.key === key) { 43 trigger(); 44 } 45 }); 46 47 return store; 48}; 49 50const useTrigger = (): [track: () => void, trigger: () => void] => { 51 const state = shallowRef(); 52 return [() => state.value, () => triggerRef(state)]; 53};