vue-localstorage-ref.ts
edited
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};