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 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}>Invalidate query</button>
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.reduce((prev, response) => {
119
- return select(response, { key, data: prev });
120
- }, null),
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.reduce((prev, response) => {
122
- return select(response, { key, data: prev });
123
- }, null),
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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "floppy-disk",
3
- "version": "2.0.0-alpha.2",
3
+ "version": "2.0.0-alpha.3",
4
4
  "description": "FloppyDisk - lightweight, simple, and powerful state management library",
5
5
  "keywords": [
6
6
  "state",