floppy-disk 1.3.0 → 1.4.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/esm/react/create-query.d.ts +14 -6
- package/esm/react/create-query.js +39 -14
- package/esm/react/create-stores.js +1 -2
- package/esm/utils/index.d.ts +1 -0
- package/esm/utils/index.js +1 -0
- package/lib/react/create-query.d.ts +14 -6
- package/lib/react/create-query.js +38 -13
- package/lib/react/create-stores.js +1 -2
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -122,6 +122,11 @@ const unsub = useCatStore.subscribe(
|
|
|
122
122
|
);
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
+
> **Examples:**
|
|
126
|
+
>
|
|
127
|
+
> - [https://codesandbox.io/.../examples/react/basic](https://codesandbox.io/p/sandbox/github/afiiif/floppy-disk/tree/main/examples/react/basic)
|
|
128
|
+
> - [https://codesandbox.io/.../examples/react/custom-reactivity](https://codesandbox.io/p/sandbox/github/afiiif/floppy-disk/tree/main/examples/react/custom-reactivity)
|
|
129
|
+
|
|
125
130
|
### Advanced Concept
|
|
126
131
|
|
|
127
132
|
Set the state **silently** (without broadcast the state change to **any subscribers**).
|
|
@@ -171,6 +176,11 @@ const useCatStore = createStore(
|
|
|
171
176
|
);
|
|
172
177
|
```
|
|
173
178
|
|
|
179
|
+
> **Examples:**
|
|
180
|
+
>
|
|
181
|
+
> - [https://codesandbox.io/.../examples/react/store-event](https://codesandbox.io/p/sandbox/github/afiiif/floppy-disk/tree/main/examples/react/store-event)
|
|
182
|
+
> - [https://codesandbox.io/.../examples/react/intercept](https://codesandbox.io/p/sandbox/github/afiiif/floppy-disk/tree/main/examples/react/intercept)
|
|
183
|
+
|
|
174
184
|
Let's go wild using IIFE.
|
|
175
185
|
|
|
176
186
|
```js
|
|
@@ -228,6 +238,10 @@ function CatPageOptimized() {
|
|
|
228
238
|
}
|
|
229
239
|
```
|
|
230
240
|
|
|
241
|
+
> **Examples:**
|
|
242
|
+
>
|
|
243
|
+
> - [https://codesandbox.io/.../examples/react/watch-component](https://codesandbox.io/p/sandbox/github/afiiif/floppy-disk/tree/main/examples/react/watch-component)
|
|
244
|
+
|
|
231
245
|
Want a local state instead of global state?
|
|
232
246
|
Or, want to set the initial state inside component?
|
|
233
247
|
|
|
@@ -94,6 +94,8 @@ export type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData
|
|
|
94
94
|
pageParam: any;
|
|
95
95
|
pageParams: any[];
|
|
96
96
|
hasNextPage: boolean;
|
|
97
|
+
retryNextPageCount: number;
|
|
98
|
+
isGoingToRetryNextPage: boolean;
|
|
97
99
|
};
|
|
98
100
|
export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = CreateStoresOptions<TKey, QueryState<TKey, TResponse, TData, TError>> & {
|
|
99
101
|
select?: (response: TResponse, state: Pick<QueryState<TKey, TResponse, TData, TError>, 'data' | 'key'>) => TData;
|
|
@@ -103,12 +105,6 @@ export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any
|
|
|
103
105
|
* Defaults to `3000` (3 seconds).
|
|
104
106
|
*/
|
|
105
107
|
staleTime?: number;
|
|
106
|
-
/**
|
|
107
|
-
* Number of maximum error retries.
|
|
108
|
-
*
|
|
109
|
-
* Defaults to `1`.
|
|
110
|
-
*/
|
|
111
|
-
retry?: number | ((error: TError, key: TKey) => number);
|
|
112
108
|
/**
|
|
113
109
|
* Auto call the query when the component is mounted.
|
|
114
110
|
*
|
|
@@ -135,6 +131,18 @@ export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any
|
|
|
135
131
|
* Defaults to `true`.
|
|
136
132
|
*/
|
|
137
133
|
enabled?: boolean | ((key: TKey) => boolean);
|
|
134
|
+
/**
|
|
135
|
+
* Number of maximum error retries.
|
|
136
|
+
*
|
|
137
|
+
* Defaults to `1`.
|
|
138
|
+
*/
|
|
139
|
+
retry?: number | ((error: TError, key: TKey) => number);
|
|
140
|
+
/**
|
|
141
|
+
* Error retry delay in miliseconds.
|
|
142
|
+
*
|
|
143
|
+
* Defaults to `3000` (3 seconds).
|
|
144
|
+
*/
|
|
145
|
+
retryDelay?: number | ((error: TError, key: TKey) => number);
|
|
138
146
|
/**
|
|
139
147
|
* If set to `true`, previous `data` will be kept when fetching new data because the query key changed.
|
|
140
148
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { identityFn, noop } from '../utils';
|
|
1
|
+
import { hashStoreKey, identityFn, noop } from '../utils';
|
|
2
2
|
import { createStores } from './create-stores';
|
|
3
3
|
const getDecision = (value, param, { ifTrue, ifAlways }) => {
|
|
4
4
|
if (value === true || (typeof value === 'function' && value(param) === true)) {
|
|
@@ -29,6 +29,8 @@ const INITIAL_QUERY_STATE = {
|
|
|
29
29
|
pageParam: undefined,
|
|
30
30
|
pageParams: [undefined],
|
|
31
31
|
hasNextPage: false,
|
|
32
|
+
retryNextPageCount: 0,
|
|
33
|
+
isGoingToRetryNextPage: false,
|
|
32
34
|
};
|
|
33
35
|
const useQueryDefaultDeps = (state) => [
|
|
34
36
|
state.data,
|
|
@@ -37,14 +39,22 @@ const useQueryDefaultDeps = (state) => [
|
|
|
37
39
|
state.hasNextPage,
|
|
38
40
|
];
|
|
39
41
|
export const createQuery = (queryFn, options = {}) => {
|
|
40
|
-
const { onFirstSubscribe = noop, onSubscribe = noop, onLastUnsubscribe = noop, onBeforeChangeKey = noop, defaultDeps = useQueryDefaultDeps, select = identityFn, staleTime = DEFAULT_STALE_TIME,
|
|
42
|
+
const { onFirstSubscribe = noop, onSubscribe = noop, onLastUnsubscribe = noop, onBeforeChangeKey = noop, defaultDeps = useQueryDefaultDeps, select = identityFn, staleTime = DEFAULT_STALE_TIME, fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, retry = 1, retryDelay = 3000, keepPreviousData, getNextPageParam = () => undefined, onSuccess = noop, onError = noop, onSettled = noop, hashKeyFn = hashStoreKey, ...createStoresOptions } = options;
|
|
43
|
+
const retryTimeoutId = new Map();
|
|
44
|
+
const retryNextPageTimeoutId = new Map();
|
|
41
45
|
const useQuery = createStores(({ key: _key, get, set }) => {
|
|
42
46
|
const key = _key;
|
|
47
|
+
const getRetryProps = (error, retryCount) => {
|
|
48
|
+
const maxRetryCount = (typeof retry === 'function' ? retry(error, key) : retry) || 0;
|
|
49
|
+
const shouldRetry = retryCount < maxRetryCount;
|
|
50
|
+
const delay = (typeof retryDelay === 'function' ? retryDelay(error, key) : retryDelay) || 0;
|
|
51
|
+
return { shouldRetry, delay };
|
|
52
|
+
};
|
|
43
53
|
const forceFetch = () => {
|
|
44
54
|
const responseAllPages = [];
|
|
45
55
|
const newPageParams = [undefined];
|
|
46
56
|
let pageParam = undefined;
|
|
47
|
-
const { isWaiting, isLoading,
|
|
57
|
+
const { isWaiting, isLoading, pageParams } = get();
|
|
48
58
|
if (isWaiting || enabled === false || (typeof enabled === 'function' && !enabled(key)))
|
|
49
59
|
return;
|
|
50
60
|
if (isLoading)
|
|
@@ -52,11 +62,12 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
52
62
|
else
|
|
53
63
|
set({ isWaiting: true, isRefetching: true });
|
|
54
64
|
const callQuery = () => {
|
|
55
|
-
if (isGoingToRetry) {
|
|
65
|
+
if (get().isGoingToRetry) {
|
|
56
66
|
if (isLoading)
|
|
57
67
|
set({ isGoingToRetry: false, isWaiting: true });
|
|
58
68
|
else
|
|
59
69
|
set({ isGoingToRetry: false, isWaiting: true, isRefetching: true });
|
|
70
|
+
clearTimeout(retryTimeoutId.get(hashKeyFn(key)));
|
|
60
71
|
}
|
|
61
72
|
const stateBeforeCallQuery = { ...get(), pageParam };
|
|
62
73
|
queryFn(key, stateBeforeCallQuery)
|
|
@@ -95,6 +106,7 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
95
106
|
.catch((error) => {
|
|
96
107
|
const prevState = get();
|
|
97
108
|
const errorUpdatedAt = Date.now();
|
|
109
|
+
const { shouldRetry, delay } = getRetryProps(error, prevState.retryCount);
|
|
98
110
|
set(prevState.isSuccess
|
|
99
111
|
? {
|
|
100
112
|
isWaiting: false,
|
|
@@ -105,6 +117,7 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
105
117
|
}, null),
|
|
106
118
|
error,
|
|
107
119
|
errorUpdatedAt,
|
|
120
|
+
isGoingToRetry: shouldRetry,
|
|
108
121
|
pageParam,
|
|
109
122
|
hasNextPage: pageParam !== undefined,
|
|
110
123
|
}
|
|
@@ -113,13 +126,15 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
113
126
|
isError: true,
|
|
114
127
|
error,
|
|
115
128
|
errorUpdatedAt,
|
|
129
|
+
isGoingToRetry: shouldRetry,
|
|
116
130
|
pageParam,
|
|
117
131
|
hasNextPage: pageParam !== undefined,
|
|
118
132
|
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
133
|
+
if (shouldRetry) {
|
|
134
|
+
retryTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
|
|
135
|
+
set({ retryCount: prevState.retryCount + 1 });
|
|
136
|
+
callQuery();
|
|
137
|
+
}, delay));
|
|
123
138
|
}
|
|
124
139
|
onError(error, stateBeforeCallQuery);
|
|
125
140
|
})
|
|
@@ -143,7 +158,8 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
143
158
|
return forceFetch();
|
|
144
159
|
if (isWaitingNextPage || !hasNextPage)
|
|
145
160
|
return;
|
|
146
|
-
set({ isWaitingNextPage: true });
|
|
161
|
+
set({ isWaitingNextPage: true, isGoingToRetryNextPage: false });
|
|
162
|
+
clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(key)));
|
|
147
163
|
queryFn(key, { ...state, pageParam })
|
|
148
164
|
.then((response) => {
|
|
149
165
|
const newPageParam = getNextPageParam(response, pageParams.length);
|
|
@@ -158,12 +174,21 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
158
174
|
});
|
|
159
175
|
})
|
|
160
176
|
.catch((error) => {
|
|
177
|
+
const prevState = get();
|
|
178
|
+
const { shouldRetry, delay } = getRetryProps(error, prevState.retryNextPageCount);
|
|
161
179
|
set({
|
|
162
180
|
isWaitingNextPage: false,
|
|
163
181
|
isError: true,
|
|
164
182
|
error,
|
|
165
183
|
errorUpdatedAt: Date.now(),
|
|
184
|
+
isGoingToRetryNextPage: shouldRetry,
|
|
166
185
|
});
|
|
186
|
+
if (shouldRetry) {
|
|
187
|
+
retryNextPageTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
|
|
188
|
+
set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
|
|
189
|
+
fetchNextPage();
|
|
190
|
+
}, delay));
|
|
191
|
+
}
|
|
167
192
|
});
|
|
168
193
|
};
|
|
169
194
|
const setResponse = (responseSetter) => {
|
|
@@ -214,9 +239,6 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
214
239
|
},
|
|
215
240
|
};
|
|
216
241
|
}, (() => {
|
|
217
|
-
const resetRetryCount = (key) => {
|
|
218
|
-
useQuery.set(key, { retryCount: 0 }, true);
|
|
219
|
-
};
|
|
220
242
|
const fetchWindowFocusHandler = () => {
|
|
221
243
|
useQuery.getAllWithSubscriber().forEach((state) => {
|
|
222
244
|
getDecision(fetchOnWindowFocus, state.key, {
|
|
@@ -228,6 +250,7 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
228
250
|
return {
|
|
229
251
|
...createStoresOptions,
|
|
230
252
|
defaultDeps,
|
|
253
|
+
hashKeyFn,
|
|
231
254
|
onFirstSubscribe: (state) => {
|
|
232
255
|
if (typeof window !== 'undefined' && fetchOnWindowFocus) {
|
|
233
256
|
window.addEventListener('focus', fetchWindowFocusHandler);
|
|
@@ -243,9 +266,11 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
243
266
|
},
|
|
244
267
|
onLastUnsubscribe: (state) => {
|
|
245
268
|
if (typeof window !== 'undefined' && fetchOnWindowFocus) {
|
|
246
|
-
window.
|
|
269
|
+
window.removeEventListener('focus', fetchWindowFocusHandler);
|
|
247
270
|
}
|
|
248
|
-
|
|
271
|
+
useQuery.set(state.key, { retryCount: 0, retryNextPageCount: 0 }, true);
|
|
272
|
+
clearTimeout(retryTimeoutId.get(hashKeyFn(state.key)));
|
|
273
|
+
clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(state.key)));
|
|
249
274
|
onLastUnsubscribe(state);
|
|
250
275
|
},
|
|
251
276
|
onBeforeChangeKey: (nextKey, prevKey) => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import { noop } from '../utils';
|
|
2
|
+
import { hashStoreKey, noop } from '../utils';
|
|
3
3
|
import { initStore, } from '../vanilla';
|
|
4
|
-
const hashStoreKey = (obj) => JSON.stringify(obj, Object.keys(obj).sort());
|
|
5
4
|
export const createStores = (initializer, options = {}) => {
|
|
6
5
|
const { onBeforeChangeKey = noop, defaultDeps, hashKeyFn = hashStoreKey } = options;
|
|
7
6
|
const stores = new Map();
|
package/esm/utils/index.d.ts
CHANGED
package/esm/utils/index.js
CHANGED
|
@@ -94,6 +94,8 @@ export type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData
|
|
|
94
94
|
pageParam: any;
|
|
95
95
|
pageParams: any[];
|
|
96
96
|
hasNextPage: boolean;
|
|
97
|
+
retryNextPageCount: number;
|
|
98
|
+
isGoingToRetryNextPage: boolean;
|
|
97
99
|
};
|
|
98
100
|
export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any, TData = TResponse, TError = unknown> = CreateStoresOptions<TKey, QueryState<TKey, TResponse, TData, TError>> & {
|
|
99
101
|
select?: (response: TResponse, state: Pick<QueryState<TKey, TResponse, TData, TError>, 'data' | 'key'>) => TData;
|
|
@@ -103,12 +105,6 @@ export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any
|
|
|
103
105
|
* Defaults to `3000` (3 seconds).
|
|
104
106
|
*/
|
|
105
107
|
staleTime?: number;
|
|
106
|
-
/**
|
|
107
|
-
* Number of maximum error retries.
|
|
108
|
-
*
|
|
109
|
-
* Defaults to `1`.
|
|
110
|
-
*/
|
|
111
|
-
retry?: number | ((error: TError, key: TKey) => number);
|
|
112
108
|
/**
|
|
113
109
|
* Auto call the query when the component is mounted.
|
|
114
110
|
*
|
|
@@ -135,6 +131,18 @@ export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any
|
|
|
135
131
|
* Defaults to `true`.
|
|
136
132
|
*/
|
|
137
133
|
enabled?: boolean | ((key: TKey) => boolean);
|
|
134
|
+
/**
|
|
135
|
+
* Number of maximum error retries.
|
|
136
|
+
*
|
|
137
|
+
* Defaults to `1`.
|
|
138
|
+
*/
|
|
139
|
+
retry?: number | ((error: TError, key: TKey) => number);
|
|
140
|
+
/**
|
|
141
|
+
* Error retry delay in miliseconds.
|
|
142
|
+
*
|
|
143
|
+
* Defaults to `3000` (3 seconds).
|
|
144
|
+
*/
|
|
145
|
+
retryDelay?: number | ((error: TError, key: TKey) => number);
|
|
138
146
|
/**
|
|
139
147
|
* If set to `true`, previous `data` will be kept when fetching new data because the query key changed.
|
|
140
148
|
*
|
|
@@ -32,6 +32,8 @@ const INITIAL_QUERY_STATE = {
|
|
|
32
32
|
pageParam: undefined,
|
|
33
33
|
pageParams: [undefined],
|
|
34
34
|
hasNextPage: false,
|
|
35
|
+
retryNextPageCount: 0,
|
|
36
|
+
isGoingToRetryNextPage: false,
|
|
35
37
|
};
|
|
36
38
|
const useQueryDefaultDeps = (state) => [
|
|
37
39
|
state.data,
|
|
@@ -40,14 +42,22 @@ const useQueryDefaultDeps = (state) => [
|
|
|
40
42
|
state.hasNextPage,
|
|
41
43
|
];
|
|
42
44
|
const createQuery = (queryFn, options = {}) => {
|
|
43
|
-
const { onFirstSubscribe = utils_1.noop, onSubscribe = utils_1.noop, onLastUnsubscribe = utils_1.noop, onBeforeChangeKey = utils_1.noop, defaultDeps = useQueryDefaultDeps, select = utils_1.identityFn, staleTime = DEFAULT_STALE_TIME,
|
|
45
|
+
const { onFirstSubscribe = utils_1.noop, onSubscribe = utils_1.noop, onLastUnsubscribe = utils_1.noop, onBeforeChangeKey = utils_1.noop, defaultDeps = useQueryDefaultDeps, select = utils_1.identityFn, staleTime = DEFAULT_STALE_TIME, fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, retry = 1, retryDelay = 3000, keepPreviousData, getNextPageParam = () => undefined, onSuccess = utils_1.noop, onError = utils_1.noop, onSettled = utils_1.noop, hashKeyFn = utils_1.hashStoreKey, ...createStoresOptions } = options;
|
|
46
|
+
const retryTimeoutId = new Map();
|
|
47
|
+
const retryNextPageTimeoutId = new Map();
|
|
44
48
|
const useQuery = (0, create_stores_1.createStores)(({ key: _key, get, set }) => {
|
|
45
49
|
const key = _key;
|
|
50
|
+
const getRetryProps = (error, retryCount) => {
|
|
51
|
+
const maxRetryCount = (typeof retry === 'function' ? retry(error, key) : retry) || 0;
|
|
52
|
+
const shouldRetry = retryCount < maxRetryCount;
|
|
53
|
+
const delay = (typeof retryDelay === 'function' ? retryDelay(error, key) : retryDelay) || 0;
|
|
54
|
+
return { shouldRetry, delay };
|
|
55
|
+
};
|
|
46
56
|
const forceFetch = () => {
|
|
47
57
|
const responseAllPages = [];
|
|
48
58
|
const newPageParams = [undefined];
|
|
49
59
|
let pageParam = undefined;
|
|
50
|
-
const { isWaiting, isLoading,
|
|
60
|
+
const { isWaiting, isLoading, pageParams } = get();
|
|
51
61
|
if (isWaiting || enabled === false || (typeof enabled === 'function' && !enabled(key)))
|
|
52
62
|
return;
|
|
53
63
|
if (isLoading)
|
|
@@ -55,11 +65,12 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
55
65
|
else
|
|
56
66
|
set({ isWaiting: true, isRefetching: true });
|
|
57
67
|
const callQuery = () => {
|
|
58
|
-
if (isGoingToRetry) {
|
|
68
|
+
if (get().isGoingToRetry) {
|
|
59
69
|
if (isLoading)
|
|
60
70
|
set({ isGoingToRetry: false, isWaiting: true });
|
|
61
71
|
else
|
|
62
72
|
set({ isGoingToRetry: false, isWaiting: true, isRefetching: true });
|
|
73
|
+
clearTimeout(retryTimeoutId.get(hashKeyFn(key)));
|
|
63
74
|
}
|
|
64
75
|
const stateBeforeCallQuery = { ...get(), pageParam };
|
|
65
76
|
queryFn(key, stateBeforeCallQuery)
|
|
@@ -98,6 +109,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
98
109
|
.catch((error) => {
|
|
99
110
|
const prevState = get();
|
|
100
111
|
const errorUpdatedAt = Date.now();
|
|
112
|
+
const { shouldRetry, delay } = getRetryProps(error, prevState.retryCount);
|
|
101
113
|
set(prevState.isSuccess
|
|
102
114
|
? {
|
|
103
115
|
isWaiting: false,
|
|
@@ -108,6 +120,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
108
120
|
}, null),
|
|
109
121
|
error,
|
|
110
122
|
errorUpdatedAt,
|
|
123
|
+
isGoingToRetry: shouldRetry,
|
|
111
124
|
pageParam,
|
|
112
125
|
hasNextPage: pageParam !== undefined,
|
|
113
126
|
}
|
|
@@ -116,13 +129,15 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
116
129
|
isError: true,
|
|
117
130
|
error,
|
|
118
131
|
errorUpdatedAt,
|
|
132
|
+
isGoingToRetry: shouldRetry,
|
|
119
133
|
pageParam,
|
|
120
134
|
hasNextPage: pageParam !== undefined,
|
|
121
135
|
});
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
136
|
+
if (shouldRetry) {
|
|
137
|
+
retryTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
|
|
138
|
+
set({ retryCount: prevState.retryCount + 1 });
|
|
139
|
+
callQuery();
|
|
140
|
+
}, delay));
|
|
126
141
|
}
|
|
127
142
|
onError(error, stateBeforeCallQuery);
|
|
128
143
|
})
|
|
@@ -146,7 +161,8 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
146
161
|
return forceFetch();
|
|
147
162
|
if (isWaitingNextPage || !hasNextPage)
|
|
148
163
|
return;
|
|
149
|
-
set({ isWaitingNextPage: true });
|
|
164
|
+
set({ isWaitingNextPage: true, isGoingToRetryNextPage: false });
|
|
165
|
+
clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(key)));
|
|
150
166
|
queryFn(key, { ...state, pageParam })
|
|
151
167
|
.then((response) => {
|
|
152
168
|
const newPageParam = getNextPageParam(response, pageParams.length);
|
|
@@ -161,12 +177,21 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
161
177
|
});
|
|
162
178
|
})
|
|
163
179
|
.catch((error) => {
|
|
180
|
+
const prevState = get();
|
|
181
|
+
const { shouldRetry, delay } = getRetryProps(error, prevState.retryNextPageCount);
|
|
164
182
|
set({
|
|
165
183
|
isWaitingNextPage: false,
|
|
166
184
|
isError: true,
|
|
167
185
|
error,
|
|
168
186
|
errorUpdatedAt: Date.now(),
|
|
187
|
+
isGoingToRetryNextPage: shouldRetry,
|
|
169
188
|
});
|
|
189
|
+
if (shouldRetry) {
|
|
190
|
+
retryNextPageTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
|
|
191
|
+
set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
|
|
192
|
+
fetchNextPage();
|
|
193
|
+
}, delay));
|
|
194
|
+
}
|
|
170
195
|
});
|
|
171
196
|
};
|
|
172
197
|
const setResponse = (responseSetter) => {
|
|
@@ -217,9 +242,6 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
217
242
|
},
|
|
218
243
|
};
|
|
219
244
|
}, (() => {
|
|
220
|
-
const resetRetryCount = (key) => {
|
|
221
|
-
useQuery.set(key, { retryCount: 0 }, true);
|
|
222
|
-
};
|
|
223
245
|
const fetchWindowFocusHandler = () => {
|
|
224
246
|
useQuery.getAllWithSubscriber().forEach((state) => {
|
|
225
247
|
getDecision(fetchOnWindowFocus, state.key, {
|
|
@@ -231,6 +253,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
231
253
|
return {
|
|
232
254
|
...createStoresOptions,
|
|
233
255
|
defaultDeps,
|
|
256
|
+
hashKeyFn,
|
|
234
257
|
onFirstSubscribe: (state) => {
|
|
235
258
|
if (typeof window !== 'undefined' && fetchOnWindowFocus) {
|
|
236
259
|
window.addEventListener('focus', fetchWindowFocusHandler);
|
|
@@ -246,9 +269,11 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
246
269
|
},
|
|
247
270
|
onLastUnsubscribe: (state) => {
|
|
248
271
|
if (typeof window !== 'undefined' && fetchOnWindowFocus) {
|
|
249
|
-
window.
|
|
272
|
+
window.removeEventListener('focus', fetchWindowFocusHandler);
|
|
250
273
|
}
|
|
251
|
-
|
|
274
|
+
useQuery.set(state.key, { retryCount: 0, retryNextPageCount: 0 }, true);
|
|
275
|
+
clearTimeout(retryTimeoutId.get(hashKeyFn(state.key)));
|
|
276
|
+
clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(state.key)));
|
|
252
277
|
onLastUnsubscribe(state);
|
|
253
278
|
},
|
|
254
279
|
onBeforeChangeKey: (nextKey, prevKey) => {
|
|
@@ -4,9 +4,8 @@ exports.createStores = void 0;
|
|
|
4
4
|
const react_1 = require("react");
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
6
|
const vanilla_1 = require("../vanilla");
|
|
7
|
-
const hashStoreKey = (obj) => JSON.stringify(obj, Object.keys(obj).sort());
|
|
8
7
|
const createStores = (initializer, options = {}) => {
|
|
9
|
-
const { onBeforeChangeKey = utils_1.noop, defaultDeps, hashKeyFn = hashStoreKey } = options;
|
|
8
|
+
const { onBeforeChangeKey = utils_1.noop, defaultDeps, hashKeyFn = utils_1.hashStoreKey } = options;
|
|
10
9
|
const stores = new Map();
|
|
11
10
|
const getStore = (_key) => {
|
|
12
11
|
const key = _key || {};
|
package/lib/utils/index.d.ts
CHANGED
package/lib/utils/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.identityFn = exports.noop = void 0;
|
|
3
|
+
exports.hashStoreKey = exports.identityFn = exports.noop = void 0;
|
|
4
4
|
const noop = () => { };
|
|
5
5
|
exports.noop = noop;
|
|
6
6
|
const identityFn = (a) => a;
|
|
7
7
|
exports.identityFn = identityFn;
|
|
8
|
+
const hashStoreKey = (obj) => JSON.stringify(obj, Object.keys(obj).sort());
|
|
9
|
+
exports.hashStoreKey = hashStoreKey;
|