mirror of
https://github.com/cinnyapp/cinny.git
synced 2025-11-13 10:40:28 +03:00
Add a method to async interact with the local storage
This commit is contained in:
parent
fd2d7fff17
commit
89695a9acc
1 changed files with 48 additions and 0 deletions
48
src/app/state/utils/atomWithIndexedDB.ts
Normal file
48
src/app/state/utils/atomWithIndexedDB.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import { atom, PrimitiveAtom } from 'jotai';
|
||||
import type { SetStateAction } from 'jotai';
|
||||
import { get as getFromDB, set as setInDB } from 'idb-keyval';
|
||||
|
||||
export const setIndexedDBItem = async <T>(key: string, value: T) => {
|
||||
await setInDB(key, value);
|
||||
};
|
||||
|
||||
export const atomWithIndexedDB = <T>(key: string, initialValue: T): PrimitiveAtom<T> => {
|
||||
const channel = new BroadcastChannel(key);
|
||||
|
||||
const baseAtom = atom(initialValue);
|
||||
let isInitialized = false;
|
||||
|
||||
baseAtom.onMount = (setAtom) => {
|
||||
(async () => {
|
||||
const storedValue = await getFromDB<T>(key);
|
||||
if (storedValue !== undefined && !isInitialized) {
|
||||
setAtom(storedValue);
|
||||
}
|
||||
isInitialized = true;
|
||||
})();
|
||||
|
||||
const handleChange = (event: MessageEvent) => {
|
||||
setAtom(event.data);
|
||||
};
|
||||
channel.addEventListener('message', handleChange);
|
||||
return () => {
|
||||
channel.removeEventListener('message', handleChange);
|
||||
};
|
||||
};
|
||||
|
||||
const derivedAtom = atom<T, [SetStateAction<T>], void>(
|
||||
(get) => get(baseAtom),
|
||||
(get, set, update: SetStateAction<T>) => {
|
||||
const currentValue = get(baseAtom);
|
||||
const newValue =
|
||||
typeof update === 'function' ? (update as (prev: T) => T)(currentValue) : update;
|
||||
|
||||
isInitialized = true;
|
||||
set(baseAtom, newValue);
|
||||
setIndexedDBItem(key, newValue);
|
||||
channel.postMessage(newValue);
|
||||
}
|
||||
);
|
||||
|
||||
return derivedAtom;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue