UNPKG

1.53 kBJavaScriptView Raw
1import { produce } from 'immer';
2import { atom, useAtom } from 'jotai';
3import { useCallback } from 'react';
4
5function atomWithImmer(initialValue) {
6 const anAtom = atom(initialValue, (get, set, fn) => set(anAtom, produce(get(anAtom), (draft) => fn(draft))));
7 return anAtom;
8}
9
10function useImmerAtom(anAtom) {
11 const [state, setState] = useAtom(anAtom);
12 const setStateWithImmer = useCallback((fn) => {
13 setState(produce((draft) => fn(draft)));
14 }, [setState]);
15 return [state, setStateWithImmer];
16}
17
18const getWeakCacheItem = (cache, deps) => {
19 const [dep, ...rest] = deps;
20 const entry = cache.get(dep);
21 if (!entry) {
22 return;
23 }
24 if (!rest.length) {
25 return entry[1];
26 }
27 return getWeakCacheItem(entry[0], rest);
28};
29const setWeakCacheItem = (cache, deps, item) => {
30 const [dep, ...rest] = deps;
31 let entry = cache.get(dep);
32 if (!entry) {
33 entry = [new WeakMap()];
34 cache.set(dep, entry);
35 }
36 if (!rest.length) {
37 entry[1] = item;
38 return;
39 }
40 setWeakCacheItem(entry[0], rest, item);
41};
42
43const withImmerCache = new WeakMap();
44function withImmer(anAtom) {
45 const deps = [anAtom];
46 const cachedAtom = getWeakCacheItem(withImmerCache, deps);
47 if (cachedAtom) {
48 return cachedAtom;
49 }
50 const derivedAtom = atom((get) => get(anAtom), (get, set, fn) => set(anAtom, produce(get(anAtom), (draft) => fn(draft))));
51 derivedAtom.scope = anAtom.scope;
52 setWeakCacheItem(withImmerCache, deps, derivedAtom);
53 return derivedAtom;
54}
55
56export { atomWithImmer, useImmerAtom, withImmer };