UNPKG

5.89 kBJavaScriptView Raw
1import { QueryClient, QueryObserver, InfiniteQueryObserver, isCancelledError } from 'react-query';
2import { atom } from 'jotai';
3
4const queryClientAtom = atom(new QueryClient());
5
6function atomWithQuery(createQuery, getQueryClient = (get) => get(queryClientAtom)) {
7 const queryDataAtom = atom((get) => {
8 const queryClient = getQueryClient(get);
9 const options = typeof createQuery === "function" ? createQuery(get) : createQuery;
10 const defaultedOptions = queryClient.defaultQueryOptions(options);
11 const observer = new QueryObserver(queryClient, defaultedOptions);
12 const initialResult = observer.getCurrentResult();
13 let resolve = null;
14 const resultAtom = atom(initialResult.data === void 0 && options.enabled !== false ? new Promise((r) => {
15 resolve = r;
16 }) : initialResult);
17 let setResult = () => {
18 throw new Error("setting result without mount");
19 };
20 const state = {
21 isMounted: false,
22 unsubscribe: null
23 };
24 const listener = (result) => {
25 if (result.isFetching || !result.isError && result.data === void 0) {
26 return;
27 }
28 if (resolve) {
29 setTimeout(() => {
30 var _a;
31 if (!state.isMounted) {
32 (_a = state.unsubscribe) == null ? void 0 : _a.call(state);
33 state.unsubscribe = null;
34 }
35 }, 1e3);
36 resolve(result);
37 resolve = null;
38 } else {
39 setResult(result);
40 }
41 };
42 if (options.enabled !== false) {
43 state.unsubscribe = observer.subscribe(listener);
44 }
45 resultAtom.onMount = (update) => {
46 setResult = update;
47 state.isMounted = true;
48 if (options.enabled !== false && !state.unsubscribe) {
49 state.unsubscribe = observer.subscribe(listener);
50 listener(observer.getCurrentResult());
51 }
52 return () => {
53 var _a;
54 return (_a = state.unsubscribe) == null ? void 0 : _a.call(state);
55 };
56 };
57 return { options, resultAtom, observer, state };
58 }, (get, set, action) => {
59 var _a;
60 const { options, resultAtom, observer, state } = get(queryDataAtom);
61 if (options.enabled === false) {
62 return;
63 }
64 switch (action.type) {
65 case "refetch": {
66 set(resultAtom, new Promise(() => {
67 }));
68 if (!state.isMounted) {
69 (_a = state.unsubscribe) == null ? void 0 : _a.call(state);
70 state.unsubscribe = null;
71 }
72 return observer.refetch({ cancelRefetch: true }).then((result) => {
73 set(resultAtom, result);
74 });
75 }
76 }
77 });
78 const queryAtom = atom((get) => {
79 const { resultAtom } = get(queryDataAtom);
80 const result = get(resultAtom);
81 if (result.isError) {
82 throw result.error;
83 }
84 return result.data;
85 }, (_get, set, action) => set(queryDataAtom, action));
86 return queryAtom;
87}
88
89function atomWithInfiniteQuery(createQuery, getQueryClient = (get) => get(queryClientAtom)) {
90 const queryDataAtom = atom((get) => {
91 const queryClient = getQueryClient(get);
92 const options = typeof createQuery === "function" ? createQuery(get) : createQuery;
93 const defaultedOptions = queryClient.defaultQueryOptions(options);
94 const observer = new InfiniteQueryObserver(queryClient, defaultedOptions);
95 const initialResult = observer.getCurrentResult();
96 let resolve = null;
97 const resultAtom = atom(initialResult.data === void 0 && options.enabled !== false ? new Promise((r) => {
98 resolve = r;
99 }) : initialResult);
100 let setResult = () => {
101 throw new Error("setting result without mount");
102 };
103 const state = {
104 isMounted: false,
105 unsubscribe: null
106 };
107 const listener = (result) => {
108 if (result.isFetching || !result.isError && result.data === void 0 || result.isError && isCancelledError(result.error)) {
109 return;
110 }
111 if (resolve) {
112 setTimeout(() => {
113 var _a;
114 if (!state.isMounted) {
115 (_a = state.unsubscribe) == null ? void 0 : _a.call(state);
116 state.unsubscribe = null;
117 }
118 }, 1e3);
119 resolve(result);
120 resolve = null;
121 } else {
122 setResult(result);
123 }
124 };
125 if (options.enabled !== false) {
126 state.unsubscribe = observer.subscribe(listener);
127 }
128 resultAtom.onMount = (update) => {
129 setResult = update;
130 state.isMounted = true;
131 if (options.enabled !== false && !state.unsubscribe) {
132 state.unsubscribe = observer.subscribe(listener);
133 listener(observer.getCurrentResult());
134 }
135 return () => {
136 var _a;
137 return (_a = state.unsubscribe) == null ? void 0 : _a.call(state);
138 };
139 };
140 return { options, resultAtom, observer, state };
141 }, (get, set, action) => {
142 var _a;
143 const { options, resultAtom, observer, state } = get(queryDataAtom);
144 if (options.enabled === false) {
145 return;
146 }
147 switch (action.type) {
148 case "refetch": {
149 set(resultAtom, new Promise(() => {
150 }));
151 if (!state.isMounted) {
152 (_a = state.unsubscribe) == null ? void 0 : _a.call(state);
153 state.unsubscribe = null;
154 }
155 const { type: _type, ...rest } = action;
156 observer.refetch(rest).then((result) => {
157 set(resultAtom, result);
158 });
159 return;
160 }
161 case "fetchPreviousPage": {
162 observer.fetchPreviousPage();
163 return;
164 }
165 case "fetchNextPage": {
166 observer.fetchNextPage();
167 return;
168 }
169 }
170 });
171 const queryAtom = atom((get) => {
172 const { resultAtom } = get(queryDataAtom);
173 const result = get(resultAtom);
174 if (result.isError) {
175 throw result.error;
176 }
177 return result.data;
178 }, (_get, set, action) => set(queryDataAtom, action));
179 return queryAtom;
180}
181
182export { atomWithInfiniteQuery, atomWithQuery, queryClientAtom };