floppy-disk 2.0.0-alpha.2 → 2.0.0-alpha.3
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 +33 -1
- package/esm/react/create-query.js +10 -3
- package/lib/react/create-query.js +10 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,6 +32,7 @@ import { createQuery, createMutation } from 'floppy-disk'; // 7.5 kB (gzipped: 2
|
|
|
32
32
|
- [Advanced Concept](#advanced-concept)
|
|
33
33
|
- [Stores](#stores)
|
|
34
34
|
- [Query \& Mutation](#query--mutation)
|
|
35
|
+
- [Query State \& Network Fetching State](#query-state--network-fetching-state)
|
|
35
36
|
- [Single Query](#single-query)
|
|
36
37
|
- [Single Query with Params](#single-query-with-params)
|
|
37
38
|
- [Paginated Query or Infinite Query](#paginated-query-or-infinite-query)
|
|
@@ -366,12 +367,43 @@ function Control({ catId }) {
|
|
|
366
367
|
|
|
367
368
|
> Example: [https://codesandbox.io/.../examples/react/stores](https://codesandbox.io/p/sandbox/github/afiiif/floppy-disk/tree/main/examples/react/stores)
|
|
368
369
|
|
|
370
|
+
<br><br>
|
|
371
|
+
|
|
372
|
+
<p align="center">
|
|
373
|
+
— ✨ 💾 ✨ —
|
|
374
|
+
</p>
|
|
375
|
+
<br>
|
|
376
|
+
|
|
369
377
|
## Query & Mutation
|
|
370
378
|
|
|
371
379
|
With the power of `createStores` function and a bit creativity, we can easily create a hook just like `useQuery` and `useInfiniteQuery` in [React-Query](https://tanstack.com/query) using `createQuery` function.
|
|
372
380
|
|
|
373
381
|
It can dedupe multiple request, handle caching, auto-update stale data, handle retry on error, handle infinite query, and many more. With the flexibility given in `createStores`, you can extend its power according to your needs.
|
|
374
382
|
|
|
383
|
+
### Query State & Network Fetching State
|
|
384
|
+
|
|
385
|
+
There are 2 types of state: query (data) state & network fetching state.
|
|
386
|
+
|
|
387
|
+
`status`, `isLoading`, `isSuccess`, `isError` is a query data state.
|
|
388
|
+
It has no relation with network fetching state. ⚠️
|
|
389
|
+
Here is the flow of the query data state:
|
|
390
|
+
|
|
391
|
+
- Initial state when there is no data fetched.
|
|
392
|
+
`{ status: 'loading', isLoading: true, isSuccess: false, isError: false }`
|
|
393
|
+
- After data fetching:
|
|
394
|
+
- If success
|
|
395
|
+
`{ status: 'success', isLoading: false, isSuccess: true, isError: false }`
|
|
396
|
+
- If error
|
|
397
|
+
`{ status: 'error', isLoading: false, isSuccess: false, isError: true }`
|
|
398
|
+
- After data fetched successfully, you will **always** get this state:
|
|
399
|
+
`{ status: 'success', isLoading: false, isSuccess: true, isError: false }`
|
|
400
|
+
- If a refetch is fired and got error, the state would be:
|
|
401
|
+
`{ status: 'success', isLoading: false, isSuccess: true, isError: false, isRefetchError: true }`
|
|
402
|
+
The previouse success response will be kept.
|
|
403
|
+
|
|
404
|
+
For network fetching state, we use `isWaiting`.
|
|
405
|
+
The value will be `true` if the query is called and still waiting for the response.
|
|
406
|
+
|
|
375
407
|
### Single Query
|
|
376
408
|
|
|
377
409
|
```jsx
|
|
@@ -419,7 +451,7 @@ function Actions() {
|
|
|
419
451
|
<>
|
|
420
452
|
<button onClick={fetch}>Call query if the query data is stale</button>
|
|
421
453
|
<button onClick={forceFetch}>Call query</button>
|
|
422
|
-
<button onClick={markAsStale}>
|
|
454
|
+
<button onClick={markAsStale}>Mark as stale</button>
|
|
423
455
|
<button onClick={reset}>Reset query</button>
|
|
424
456
|
</>
|
|
425
457
|
);
|
|
@@ -44,6 +44,7 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
44
44
|
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;
|
|
45
45
|
const retryTimeoutId = new Map();
|
|
46
46
|
const retryNextPageTimeoutId = new Map();
|
|
47
|
+
const preventReplaceResponse = new Map(); // Prevent optimistic data to be replaced
|
|
47
48
|
const useQuery = createStores(({ key: _key, get, set }) => {
|
|
48
49
|
const key = _key;
|
|
49
50
|
const getRetryProps = (error, retryCount) => {
|
|
@@ -72,8 +73,11 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
72
73
|
clearTimeout(retryTimeoutId.get(hashKeyFn(key)));
|
|
73
74
|
}
|
|
74
75
|
const stateBeforeCallQuery = { ...get(), pageParam };
|
|
76
|
+
preventReplaceResponse.set(hashKeyFn(key), false);
|
|
75
77
|
queryFn(key, stateBeforeCallQuery)
|
|
76
78
|
.then((response) => {
|
|
79
|
+
if (preventReplaceResponse.get(hashKeyFn(key)))
|
|
80
|
+
return;
|
|
77
81
|
responseAllPages.push(response);
|
|
78
82
|
const newPageParam = getNextPageParam(response, responseAllPages.length);
|
|
79
83
|
newPageParams.push(newPageParam);
|
|
@@ -115,9 +119,11 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
115
119
|
isWaiting: false,
|
|
116
120
|
isRefetching: false,
|
|
117
121
|
isRefetchError: true,
|
|
118
|
-
data: responseAllPages.
|
|
119
|
-
|
|
120
|
-
|
|
122
|
+
data: responseAllPages.length
|
|
123
|
+
? responseAllPages.reduce((prev, response) => {
|
|
124
|
+
return select(response, { key, data: prev });
|
|
125
|
+
}, null)
|
|
126
|
+
: prevState.data,
|
|
121
127
|
error,
|
|
122
128
|
errorUpdatedAt,
|
|
123
129
|
isGoingToRetry: shouldRetry,
|
|
@@ -301,6 +307,7 @@ export const createQuery = (queryFn, options = {}) => {
|
|
|
301
307
|
response: optimisticResponse,
|
|
302
308
|
data: select(optimisticResponse, { key: key, data: null }),
|
|
303
309
|
});
|
|
310
|
+
preventReplaceResponse.set(hashKeyFn(key), true);
|
|
304
311
|
const revert = () => {
|
|
305
312
|
useQuery.set(key, {
|
|
306
313
|
isOptimisticData: false,
|
|
@@ -47,6 +47,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
47
47
|
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;
|
|
48
48
|
const retryTimeoutId = new Map();
|
|
49
49
|
const retryNextPageTimeoutId = new Map();
|
|
50
|
+
const preventReplaceResponse = new Map(); // Prevent optimistic data to be replaced
|
|
50
51
|
const useQuery = (0, create_stores_1.createStores)(({ key: _key, get, set }) => {
|
|
51
52
|
const key = _key;
|
|
52
53
|
const getRetryProps = (error, retryCount) => {
|
|
@@ -75,8 +76,11 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
75
76
|
clearTimeout(retryTimeoutId.get(hashKeyFn(key)));
|
|
76
77
|
}
|
|
77
78
|
const stateBeforeCallQuery = { ...get(), pageParam };
|
|
79
|
+
preventReplaceResponse.set(hashKeyFn(key), false);
|
|
78
80
|
queryFn(key, stateBeforeCallQuery)
|
|
79
81
|
.then((response) => {
|
|
82
|
+
if (preventReplaceResponse.get(hashKeyFn(key)))
|
|
83
|
+
return;
|
|
80
84
|
responseAllPages.push(response);
|
|
81
85
|
const newPageParam = getNextPageParam(response, responseAllPages.length);
|
|
82
86
|
newPageParams.push(newPageParam);
|
|
@@ -118,9 +122,11 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
118
122
|
isWaiting: false,
|
|
119
123
|
isRefetching: false,
|
|
120
124
|
isRefetchError: true,
|
|
121
|
-
data: responseAllPages.
|
|
122
|
-
|
|
123
|
-
|
|
125
|
+
data: responseAllPages.length
|
|
126
|
+
? responseAllPages.reduce((prev, response) => {
|
|
127
|
+
return select(response, { key, data: prev });
|
|
128
|
+
}, null)
|
|
129
|
+
: prevState.data,
|
|
124
130
|
error,
|
|
125
131
|
errorUpdatedAt,
|
|
126
132
|
isGoingToRetry: shouldRetry,
|
|
@@ -304,6 +310,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
304
310
|
response: optimisticResponse,
|
|
305
311
|
data: select(optimisticResponse, { key: key, data: null }),
|
|
306
312
|
});
|
|
313
|
+
preventReplaceResponse.set(hashKeyFn(key), true);
|
|
307
314
|
const revert = () => {
|
|
308
315
|
useQuery.set(key, {
|
|
309
316
|
isOptimisticData: false,
|