floppy-disk 2.5.0 → 2.6.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.
@@ -0,0 +1,167 @@
1
+ import { Maybe } from '../utils';
2
+ import { SelectDeps } from '../vanilla';
3
+ import { CreateQueryOptions, QueryState } from './create-query';
4
+ import { StoreKey } from './create-stores';
5
+ export declare const createBiDirectionQuery: <TKey extends StoreKey = StoreKey, TResponse = any, TData extends any[] = any[], TError = unknown, TPageParam = any>(queryFn: (key: TKey, state: QueryState<TKey, TResponse, TData, TError, TPageParam>, direction: 'prev' | 'next') => Promise<TResponse>, options: Omit<CreateQueryOptions<TKey, TResponse, TData, TError, TPageParam>, "select" | "getNextPageParam"> & {
6
+ getPrevPageParam: (lastPage: TResponse, index: number, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => Maybe<TPageParam>;
7
+ getNextPageParam: (lastPage: TResponse, index: number, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => Maybe<TPageParam>;
8
+ select: (response: TResponse, state: Pick<QueryState<TKey, TResponse, TData, TError, TPageParam>, "data" | "key">, direction: 'prev' | 'next') => TData;
9
+ }) => {
10
+ (...args: [Maybe<TKey>, SelectDeps<QueryState<TKey, TResponse, TData, TError, TPageParam>>?] | [SelectDeps<QueryState<TKey, TResponse, TData, TError, TPageParam>>?]): {
11
+ data: (never[] | TData)[number][];
12
+ fetchPrevPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
13
+ hasPrevPage: boolean;
14
+ isWaitingPrevPage: boolean;
15
+ key: TKey;
16
+ keyHash: string;
17
+ fetch: () => void;
18
+ forceFetch: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
19
+ fetchNextPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
20
+ reset: () => void;
21
+ optimisticUpdate: (response: TResponse | ((prevState: QueryState<TKey, TResponse, TData, TError, TPageParam>) => TResponse)) => {
22
+ revert: () => void;
23
+ invalidate: () => void;
24
+ };
25
+ isWaiting: boolean;
26
+ isWaitingNextPage: boolean;
27
+ isRefetching: boolean;
28
+ isRefetchError: boolean;
29
+ isPreviousData: boolean;
30
+ isOptimisticData: boolean;
31
+ error: TError | undefined;
32
+ errorUpdatedAt: number | undefined;
33
+ retryCount: number;
34
+ isGoingToRetry: boolean;
35
+ pageParam: Maybe<TPageParam>;
36
+ pageParams: Maybe<TPageParam>[];
37
+ hasNextPage: boolean;
38
+ retryNextPageCount: number;
39
+ isGoingToRetryNextPage: boolean;
40
+ status: "loading";
41
+ isLoading: true;
42
+ isSuccess: false;
43
+ isError: false;
44
+ response: undefined;
45
+ responseUpdatedAt: undefined;
46
+ } | {
47
+ data: (never[] | TData)[number][];
48
+ fetchPrevPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
49
+ hasPrevPage: boolean;
50
+ isWaitingPrevPage: boolean;
51
+ key: TKey;
52
+ keyHash: string;
53
+ fetch: () => void;
54
+ forceFetch: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
55
+ fetchNextPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
56
+ reset: () => void;
57
+ optimisticUpdate: (response: TResponse | ((prevState: QueryState<TKey, TResponse, TData, TError, TPageParam>) => TResponse)) => {
58
+ revert: () => void;
59
+ invalidate: () => void;
60
+ };
61
+ isWaiting: boolean;
62
+ isWaitingNextPage: boolean;
63
+ isRefetching: boolean;
64
+ isRefetchError: boolean;
65
+ isPreviousData: boolean;
66
+ isOptimisticData: boolean;
67
+ error: TError | undefined;
68
+ errorUpdatedAt: number | undefined;
69
+ retryCount: number;
70
+ isGoingToRetry: boolean;
71
+ pageParam: Maybe<TPageParam>;
72
+ pageParams: Maybe<TPageParam>[];
73
+ hasNextPage: boolean;
74
+ retryNextPageCount: number;
75
+ isGoingToRetryNextPage: boolean;
76
+ status: "error";
77
+ isLoading: false;
78
+ isSuccess: false;
79
+ isError: true;
80
+ response: undefined;
81
+ responseUpdatedAt: undefined;
82
+ } | {
83
+ data: (never[] | TData)[number][];
84
+ fetchPrevPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
85
+ hasPrevPage: boolean;
86
+ isWaitingPrevPage: boolean;
87
+ key: TKey;
88
+ keyHash: string;
89
+ fetch: () => void;
90
+ forceFetch: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
91
+ fetchNextPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
92
+ reset: () => void;
93
+ optimisticUpdate: (response: TResponse | ((prevState: QueryState<TKey, TResponse, TData, TError, TPageParam>) => TResponse)) => {
94
+ revert: () => void;
95
+ invalidate: () => void;
96
+ };
97
+ isWaiting: boolean;
98
+ isWaitingNextPage: boolean;
99
+ isRefetching: boolean;
100
+ isRefetchError: boolean;
101
+ isPreviousData: boolean;
102
+ isOptimisticData: boolean;
103
+ error: TError | undefined;
104
+ errorUpdatedAt: number | undefined;
105
+ retryCount: number;
106
+ isGoingToRetry: boolean;
107
+ pageParam: Maybe<TPageParam>;
108
+ pageParams: Maybe<TPageParam>[];
109
+ hasNextPage: boolean;
110
+ retryNextPageCount: number;
111
+ isGoingToRetryNextPage: boolean;
112
+ status: "success";
113
+ isLoading: false;
114
+ isSuccess: true;
115
+ isError: false;
116
+ response: TResponse;
117
+ responseUpdatedAt: number | undefined;
118
+ };
119
+ get(): {
120
+ prev: QueryState<TKey, TResponse, TData, TError, TPageParam>;
121
+ next: QueryState<TKey, TResponse, TData, TError, TPageParam>;
122
+ };
123
+ setInitialResponse: (options: {
124
+ key?: Maybe<TKey>;
125
+ response: TResponse;
126
+ skipRevalidation?: boolean | undefined;
127
+ }) => void;
128
+ reset(): void;
129
+ resetSpecificKey(key: Maybe<TKey>): void;
130
+ invalidate: () => void;
131
+ invalidateSpecificKey: (key?: Maybe<TKey>) => void;
132
+ suspend: (key?: Maybe<TKey>) => {
133
+ key: TKey;
134
+ keyHash: string;
135
+ fetch: () => void;
136
+ forceFetch: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
137
+ fetchNextPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
138
+ reset: () => void;
139
+ optimisticUpdate: (response: TResponse | ((prevState: QueryState<TKey, TResponse, TData, TError, TPageParam>) => TResponse)) => {
140
+ revert: () => void;
141
+ invalidate: () => void;
142
+ };
143
+ isWaiting: boolean;
144
+ isWaitingNextPage: boolean;
145
+ isRefetching: boolean;
146
+ isRefetchError: boolean;
147
+ isPreviousData: boolean;
148
+ isOptimisticData: boolean;
149
+ error: TError | undefined;
150
+ errorUpdatedAt: number | undefined;
151
+ retryCount: number;
152
+ isGoingToRetry: boolean;
153
+ pageParam: Maybe<TPageParam>;
154
+ pageParams: Maybe<TPageParam>[];
155
+ hasNextPage: boolean;
156
+ retryNextPageCount: number;
157
+ isGoingToRetryNextPage: boolean;
158
+ } & {
159
+ status: "success";
160
+ isLoading: false;
161
+ isSuccess: true;
162
+ isError: false;
163
+ data: TData;
164
+ response: TResponse;
165
+ responseUpdatedAt: number | undefined;
166
+ };
167
+ };
@@ -0,0 +1,74 @@
1
+ import { hasValue } from '../utils';
2
+ import { createQuery } from './create-query';
3
+ export const createBiDirectionQuery = (queryFn, options) => {
4
+ const { getPrevPageParam, getNextPageParam, select, ...restOptions } = options;
5
+ const usePrevPagesQuery = createQuery((key, state) => queryFn(key, state, 'prev'), {
6
+ defaultDeps: (state) => [
7
+ state.isWaiting,
8
+ state.data,
9
+ state.error,
10
+ state.isWaitingNextPage,
11
+ state.hasNextPage,
12
+ ],
13
+ fetchOnMount: false,
14
+ getNextPageParam: getPrevPageParam,
15
+ select: (response, state) => select(response, state, 'prev'),
16
+ ...restOptions,
17
+ });
18
+ const useNextPagesQuery = createQuery(async (key, state) => {
19
+ const isInitialPage = state.pageParam === undefined;
20
+ const pQuery = usePrevPagesQuery.get(key);
21
+ try {
22
+ const response = await queryFn(key, state, 'next');
23
+ if (isInitialPage) {
24
+ const prevPageParam = getPrevPageParam(response, 1, pQuery);
25
+ usePrevPagesQuery.set(key, (prev) => ({
26
+ pageParams: [prevPageParam, ...prev.pageParams.slice(1)],
27
+ hasNextPage: prev.isLoading ? hasValue(prevPageParam) : prev.hasNextPage,
28
+ }));
29
+ if (!pQuery.isLoading)
30
+ pQuery.forceFetch();
31
+ }
32
+ return response;
33
+ }
34
+ catch (error) {
35
+ if (isInitialPage && !pQuery.isLoading)
36
+ pQuery.reset();
37
+ throw error;
38
+ }
39
+ }, {
40
+ getNextPageParam: getNextPageParam,
41
+ select: (response, state) => select(response, state, 'next'),
42
+ ...restOptions,
43
+ });
44
+ const useBiDirectionQuery = (...args) => {
45
+ const pQuery = usePrevPagesQuery(...args);
46
+ const nQuery = useNextPagesQuery(...args);
47
+ return {
48
+ ...nQuery,
49
+ data: [...(pQuery.data || []), ...(nQuery.data || [])],
50
+ fetchPrevPage: pQuery.fetchNextPage,
51
+ hasPrevPage: pQuery.hasNextPage,
52
+ isWaitingPrevPage: pQuery.isWaitingNextPage || (pQuery.isLoading && pQuery.isWaiting),
53
+ };
54
+ };
55
+ useBiDirectionQuery.get = () => {
56
+ return {
57
+ prev: usePrevPagesQuery.get(),
58
+ next: useNextPagesQuery.get(),
59
+ };
60
+ };
61
+ useBiDirectionQuery.setInitialResponse = useNextPagesQuery.setInitialResponse;
62
+ useBiDirectionQuery.reset = () => {
63
+ usePrevPagesQuery.reset();
64
+ useNextPagesQuery.reset();
65
+ };
66
+ useBiDirectionQuery.resetSpecificKey = (key) => {
67
+ usePrevPagesQuery.resetSpecificKey(key);
68
+ useNextPagesQuery.resetSpecificKey(key);
69
+ };
70
+ useBiDirectionQuery.invalidate = useNextPagesQuery.invalidate;
71
+ useBiDirectionQuery.invalidateSpecificKey = useNextPagesQuery.invalidateSpecificKey;
72
+ useBiDirectionQuery.suspend = useNextPagesQuery.suspend;
73
+ return useBiDirectionQuery;
74
+ };
@@ -191,7 +191,7 @@ export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any
191
191
  *
192
192
  * This function should return a variable that will be stored as `pageParam` that can be used when fetching next page.
193
193
  */
194
- getNextPageParam?: (lastPage: TResponse, index: number) => Maybe<TPageParam>;
194
+ getNextPageParam?: (lastPage: TResponse, index: number, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => Maybe<TPageParam>;
195
195
  onBeforeFetch?: (cancel: () => void, state: QueryState<TKey, TResponse, TData, TError, TPageParam>) => void;
196
196
  onSuccess?: (response: TResponse, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => void;
197
197
  onError?: (error: TError, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => void;
@@ -55,11 +55,11 @@ export const createQuery = (queryFn, options = {}) => {
55
55
  };
56
56
  const forceFetch = () => new Promise((resolve) => {
57
57
  const state = get();
58
+ const { isWaiting, isLoading, pageParams } = state;
58
59
  const responseAllPages = [];
59
- const newPageParams = [state.pageParams[0]];
60
- let pageParam = state.pageParams[0];
60
+ const newPageParams = [pageParams[0]];
61
+ let pageParam = pageParams[0];
61
62
  clearTimeout(refetchIntervalTimeoutId.get(keyHash));
62
- const { isWaiting, isLoading, pageParams } = state;
63
63
  if (isWaiting || !getValueOrComputedValue(enabled, key))
64
64
  return resolve(state);
65
65
  let shouldcancel = false;
@@ -81,8 +81,8 @@ export const createQuery = (queryFn, options = {}) => {
81
81
  set({ isGoingToRetry: false, isWaiting: true, isRefetching: true });
82
82
  clearTimeout(retryTimeoutId.get(keyHash));
83
83
  }
84
- const stateBeforeCallQuery = { ...get(), pageParam };
85
84
  preventReplaceResponse.set(keyHash, false);
85
+ const stateBeforeCallQuery = { ...get(), pageParam };
86
86
  queryFn(key, stateBeforeCallQuery)
87
87
  .then((response) => {
88
88
  if (preventReplaceResponse.get(keyHash)) {
@@ -90,7 +90,7 @@ export const createQuery = (queryFn, options = {}) => {
90
90
  return resolve(get());
91
91
  }
92
92
  responseAllPages.push(response);
93
- const newPageParam = getNextPageParam(response, responseAllPages.length);
93
+ const newPageParam = getNextPageParam(response, responseAllPages.length, stateBeforeCallQuery);
94
94
  newPageParams.push(newPageParam);
95
95
  if (hasValue(newPageParam) && newPageParams.length < pageParams.length) {
96
96
  pageParam = newPageParam;
@@ -206,7 +206,7 @@ export const createQuery = (queryFn, options = {}) => {
206
206
  const stateBeforeCallQuery = get();
207
207
  queryFn(key, { ...state, pageParam })
208
208
  .then((response) => {
209
- const newPageParam = getNextPageParam(response, pageParams.length);
209
+ const newPageParam = getNextPageParam(response, pageParams.length, stateBeforeCallQuery);
210
210
  set({
211
211
  isWaitingNextPage: false,
212
212
  response,
@@ -327,9 +327,10 @@ export const createQuery = (queryFn, options = {}) => {
327
327
  useQuery.setInitialResponse = ({ key, response, skipRevalidation }) => {
328
328
  // eslint-disable-next-line react-hooks/rules-of-hooks
329
329
  useState(() => {
330
- if (response === undefined || useQuery.get(key).data)
330
+ const state = useQuery.get(key);
331
+ if (response === undefined || state.isSuccess)
331
332
  return;
332
- const newPageParam = getNextPageParam(response, 1);
333
+ const newPageParam = getNextPageParam(response, 1, state);
333
334
  useQuery.set(key, {
334
335
  status: 'success',
335
336
  isLoading: false,
@@ -1,5 +1,6 @@
1
1
  export * from './create-store';
2
2
  export * from './create-stores';
3
3
  export * from './create-query';
4
+ export * from './create-bi-direction-query';
4
5
  export * from './create-mutation';
5
6
  export * from './with-context';
@@ -1,5 +1,6 @@
1
1
  export * from './create-store';
2
2
  export * from './create-stores';
3
3
  export * from './create-query';
4
+ export * from './create-bi-direction-query';
4
5
  export * from './create-mutation';
5
6
  export * from './with-context';
@@ -0,0 +1,167 @@
1
+ import { Maybe } from '../utils';
2
+ import { SelectDeps } from '../vanilla';
3
+ import { CreateQueryOptions, QueryState } from './create-query';
4
+ import { StoreKey } from './create-stores';
5
+ export declare const createBiDirectionQuery: <TKey extends StoreKey = StoreKey, TResponse = any, TData extends any[] = any[], TError = unknown, TPageParam = any>(queryFn: (key: TKey, state: QueryState<TKey, TResponse, TData, TError, TPageParam>, direction: 'prev' | 'next') => Promise<TResponse>, options: Omit<CreateQueryOptions<TKey, TResponse, TData, TError, TPageParam>, "select" | "getNextPageParam"> & {
6
+ getPrevPageParam: (lastPage: TResponse, index: number, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => Maybe<TPageParam>;
7
+ getNextPageParam: (lastPage: TResponse, index: number, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => Maybe<TPageParam>;
8
+ select: (response: TResponse, state: Pick<QueryState<TKey, TResponse, TData, TError, TPageParam>, "data" | "key">, direction: 'prev' | 'next') => TData;
9
+ }) => {
10
+ (...args: [Maybe<TKey>, SelectDeps<QueryState<TKey, TResponse, TData, TError, TPageParam>>?] | [SelectDeps<QueryState<TKey, TResponse, TData, TError, TPageParam>>?]): {
11
+ data: (never[] | TData)[number][];
12
+ fetchPrevPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
13
+ hasPrevPage: boolean;
14
+ isWaitingPrevPage: boolean;
15
+ key: TKey;
16
+ keyHash: string;
17
+ fetch: () => void;
18
+ forceFetch: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
19
+ fetchNextPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
20
+ reset: () => void;
21
+ optimisticUpdate: (response: TResponse | ((prevState: QueryState<TKey, TResponse, TData, TError, TPageParam>) => TResponse)) => {
22
+ revert: () => void;
23
+ invalidate: () => void;
24
+ };
25
+ isWaiting: boolean;
26
+ isWaitingNextPage: boolean;
27
+ isRefetching: boolean;
28
+ isRefetchError: boolean;
29
+ isPreviousData: boolean;
30
+ isOptimisticData: boolean;
31
+ error: TError | undefined;
32
+ errorUpdatedAt: number | undefined;
33
+ retryCount: number;
34
+ isGoingToRetry: boolean;
35
+ pageParam: Maybe<TPageParam>;
36
+ pageParams: Maybe<TPageParam>[];
37
+ hasNextPage: boolean;
38
+ retryNextPageCount: number;
39
+ isGoingToRetryNextPage: boolean;
40
+ status: "loading";
41
+ isLoading: true;
42
+ isSuccess: false;
43
+ isError: false;
44
+ response: undefined;
45
+ responseUpdatedAt: undefined;
46
+ } | {
47
+ data: (never[] | TData)[number][];
48
+ fetchPrevPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
49
+ hasPrevPage: boolean;
50
+ isWaitingPrevPage: boolean;
51
+ key: TKey;
52
+ keyHash: string;
53
+ fetch: () => void;
54
+ forceFetch: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
55
+ fetchNextPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
56
+ reset: () => void;
57
+ optimisticUpdate: (response: TResponse | ((prevState: QueryState<TKey, TResponse, TData, TError, TPageParam>) => TResponse)) => {
58
+ revert: () => void;
59
+ invalidate: () => void;
60
+ };
61
+ isWaiting: boolean;
62
+ isWaitingNextPage: boolean;
63
+ isRefetching: boolean;
64
+ isRefetchError: boolean;
65
+ isPreviousData: boolean;
66
+ isOptimisticData: boolean;
67
+ error: TError | undefined;
68
+ errorUpdatedAt: number | undefined;
69
+ retryCount: number;
70
+ isGoingToRetry: boolean;
71
+ pageParam: Maybe<TPageParam>;
72
+ pageParams: Maybe<TPageParam>[];
73
+ hasNextPage: boolean;
74
+ retryNextPageCount: number;
75
+ isGoingToRetryNextPage: boolean;
76
+ status: "error";
77
+ isLoading: false;
78
+ isSuccess: false;
79
+ isError: true;
80
+ response: undefined;
81
+ responseUpdatedAt: undefined;
82
+ } | {
83
+ data: (never[] | TData)[number][];
84
+ fetchPrevPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
85
+ hasPrevPage: boolean;
86
+ isWaitingPrevPage: boolean;
87
+ key: TKey;
88
+ keyHash: string;
89
+ fetch: () => void;
90
+ forceFetch: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
91
+ fetchNextPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
92
+ reset: () => void;
93
+ optimisticUpdate: (response: TResponse | ((prevState: QueryState<TKey, TResponse, TData, TError, TPageParam>) => TResponse)) => {
94
+ revert: () => void;
95
+ invalidate: () => void;
96
+ };
97
+ isWaiting: boolean;
98
+ isWaitingNextPage: boolean;
99
+ isRefetching: boolean;
100
+ isRefetchError: boolean;
101
+ isPreviousData: boolean;
102
+ isOptimisticData: boolean;
103
+ error: TError | undefined;
104
+ errorUpdatedAt: number | undefined;
105
+ retryCount: number;
106
+ isGoingToRetry: boolean;
107
+ pageParam: Maybe<TPageParam>;
108
+ pageParams: Maybe<TPageParam>[];
109
+ hasNextPage: boolean;
110
+ retryNextPageCount: number;
111
+ isGoingToRetryNextPage: boolean;
112
+ status: "success";
113
+ isLoading: false;
114
+ isSuccess: true;
115
+ isError: false;
116
+ response: TResponse;
117
+ responseUpdatedAt: number | undefined;
118
+ };
119
+ get(): {
120
+ prev: QueryState<TKey, TResponse, TData, TError, TPageParam>;
121
+ next: QueryState<TKey, TResponse, TData, TError, TPageParam>;
122
+ };
123
+ setInitialResponse: (options: {
124
+ key?: Maybe<TKey>;
125
+ response: TResponse;
126
+ skipRevalidation?: boolean | undefined;
127
+ }) => void;
128
+ reset(): void;
129
+ resetSpecificKey(key: Maybe<TKey>): void;
130
+ invalidate: () => void;
131
+ invalidateSpecificKey: (key?: Maybe<TKey>) => void;
132
+ suspend: (key?: Maybe<TKey>) => {
133
+ key: TKey;
134
+ keyHash: string;
135
+ fetch: () => void;
136
+ forceFetch: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
137
+ fetchNextPage: () => Promise<QueryState<TKey, TResponse, TData, TError, TPageParam>>;
138
+ reset: () => void;
139
+ optimisticUpdate: (response: TResponse | ((prevState: QueryState<TKey, TResponse, TData, TError, TPageParam>) => TResponse)) => {
140
+ revert: () => void;
141
+ invalidate: () => void;
142
+ };
143
+ isWaiting: boolean;
144
+ isWaitingNextPage: boolean;
145
+ isRefetching: boolean;
146
+ isRefetchError: boolean;
147
+ isPreviousData: boolean;
148
+ isOptimisticData: boolean;
149
+ error: TError | undefined;
150
+ errorUpdatedAt: number | undefined;
151
+ retryCount: number;
152
+ isGoingToRetry: boolean;
153
+ pageParam: Maybe<TPageParam>;
154
+ pageParams: Maybe<TPageParam>[];
155
+ hasNextPage: boolean;
156
+ retryNextPageCount: number;
157
+ isGoingToRetryNextPage: boolean;
158
+ } & {
159
+ status: "success";
160
+ isLoading: false;
161
+ isSuccess: true;
162
+ isError: false;
163
+ data: TData;
164
+ response: TResponse;
165
+ responseUpdatedAt: number | undefined;
166
+ };
167
+ };
@@ -0,0 +1,74 @@
1
+ import { hasValue } from '../utils';
2
+ import { createQuery } from './create-query';
3
+ export const createBiDirectionQuery = (queryFn, options) => {
4
+ const { getPrevPageParam, getNextPageParam, select, ...restOptions } = options;
5
+ const usePrevPagesQuery = createQuery((key, state) => queryFn(key, state, 'prev'), {
6
+ defaultDeps: (state) => [
7
+ state.isWaiting,
8
+ state.data,
9
+ state.error,
10
+ state.isWaitingNextPage,
11
+ state.hasNextPage,
12
+ ],
13
+ fetchOnMount: false,
14
+ getNextPageParam: getPrevPageParam,
15
+ select: (response, state) => select(response, state, 'prev'),
16
+ ...restOptions,
17
+ });
18
+ const useNextPagesQuery = createQuery(async (key, state) => {
19
+ const isInitialPage = state.pageParam === undefined;
20
+ const pQuery = usePrevPagesQuery.get(key);
21
+ try {
22
+ const response = await queryFn(key, state, 'next');
23
+ if (isInitialPage) {
24
+ const prevPageParam = getPrevPageParam(response, 1, pQuery);
25
+ usePrevPagesQuery.set(key, (prev) => ({
26
+ pageParams: [prevPageParam, ...prev.pageParams.slice(1)],
27
+ hasNextPage: prev.isLoading ? hasValue(prevPageParam) : prev.hasNextPage,
28
+ }));
29
+ if (!pQuery.isLoading)
30
+ pQuery.forceFetch();
31
+ }
32
+ return response;
33
+ }
34
+ catch (error) {
35
+ if (isInitialPage && !pQuery.isLoading)
36
+ pQuery.reset();
37
+ throw error;
38
+ }
39
+ }, {
40
+ getNextPageParam: getNextPageParam,
41
+ select: (response, state) => select(response, state, 'next'),
42
+ ...restOptions,
43
+ });
44
+ const useBiDirectionQuery = (...args) => {
45
+ const pQuery = usePrevPagesQuery(...args);
46
+ const nQuery = useNextPagesQuery(...args);
47
+ return {
48
+ ...nQuery,
49
+ data: [...(pQuery.data || []), ...(nQuery.data || [])],
50
+ fetchPrevPage: pQuery.fetchNextPage,
51
+ hasPrevPage: pQuery.hasNextPage,
52
+ isWaitingPrevPage: pQuery.isWaitingNextPage || (pQuery.isLoading && pQuery.isWaiting),
53
+ };
54
+ };
55
+ useBiDirectionQuery.get = () => {
56
+ return {
57
+ prev: usePrevPagesQuery.get(),
58
+ next: useNextPagesQuery.get(),
59
+ };
60
+ };
61
+ useBiDirectionQuery.setInitialResponse = useNextPagesQuery.setInitialResponse;
62
+ useBiDirectionQuery.reset = () => {
63
+ usePrevPagesQuery.reset();
64
+ useNextPagesQuery.reset();
65
+ };
66
+ useBiDirectionQuery.resetSpecificKey = (key) => {
67
+ usePrevPagesQuery.resetSpecificKey(key);
68
+ useNextPagesQuery.resetSpecificKey(key);
69
+ };
70
+ useBiDirectionQuery.invalidate = useNextPagesQuery.invalidate;
71
+ useBiDirectionQuery.invalidateSpecificKey = useNextPagesQuery.invalidateSpecificKey;
72
+ useBiDirectionQuery.suspend = useNextPagesQuery.suspend;
73
+ return useBiDirectionQuery;
74
+ };
@@ -190,7 +190,7 @@ export type CreateQueryOptions<TKey extends StoreKey = StoreKey, TResponse = any
190
190
  *
191
191
  * This function should return a variable that will be stored as `pageParam` that can be used when fetching next page.
192
192
  */
193
- getNextPageParam?: (lastPage: TResponse, index: number) => Maybe<TPageParam>;
193
+ getNextPageParam?: (lastPage: TResponse, index: number, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => Maybe<TPageParam>;
194
194
  onBeforeFetch?: (cancel: () => void, state: QueryState<TKey, TResponse, TData, TError, TPageParam>) => void;
195
195
  onSuccess?: (response: TResponse, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => void;
196
196
  onError?: (error: TError, stateBeforeCallQuery: QueryState<TKey, TResponse, TData, TError, TPageParam>) => void;
@@ -54,11 +54,11 @@ export const createQuery = (queryFn, options = {}) => {
54
54
  };
55
55
  const forceFetch = () => new Promise((resolve) => {
56
56
  const state = get();
57
+ const { isWaiting, isLoading, pageParams } = state;
57
58
  const responseAllPages = [];
58
- const newPageParams = [state.pageParams[0]];
59
- let pageParam = state.pageParams[0];
59
+ const newPageParams = [pageParams[0]];
60
+ let pageParam = pageParams[0];
60
61
  clearTimeout(refetchIntervalTimeoutId.get(keyHash));
61
- const { isWaiting, isLoading, pageParams } = state;
62
62
  if (isWaiting || !getValueOrComputedValue(enabled, key))
63
63
  return resolve(state);
64
64
  let shouldcancel = false;
@@ -80,8 +80,8 @@ export const createQuery = (queryFn, options = {}) => {
80
80
  set({ isGoingToRetry: false, isWaiting: true, isRefetching: true });
81
81
  clearTimeout(retryTimeoutId.get(keyHash));
82
82
  }
83
- const stateBeforeCallQuery = { ...get(), pageParam };
84
83
  preventReplaceResponse.set(keyHash, false);
84
+ const stateBeforeCallQuery = { ...get(), pageParam };
85
85
  queryFn(key, stateBeforeCallQuery)
86
86
  .then((response) => {
87
87
  if (preventReplaceResponse.get(keyHash)) {
@@ -89,7 +89,7 @@ export const createQuery = (queryFn, options = {}) => {
89
89
  return resolve(get());
90
90
  }
91
91
  responseAllPages.push(response);
92
- const newPageParam = getNextPageParam(response, responseAllPages.length);
92
+ const newPageParam = getNextPageParam(response, responseAllPages.length, stateBeforeCallQuery);
93
93
  newPageParams.push(newPageParam);
94
94
  if (hasValue(newPageParam) && newPageParams.length < pageParams.length) {
95
95
  pageParam = newPageParam;
@@ -205,7 +205,7 @@ export const createQuery = (queryFn, options = {}) => {
205
205
  const stateBeforeCallQuery = get();
206
206
  queryFn(key, { ...state, pageParam })
207
207
  .then((response) => {
208
- const newPageParam = getNextPageParam(response, pageParams.length);
208
+ const newPageParam = getNextPageParam(response, pageParams.length, stateBeforeCallQuery);
209
209
  set({
210
210
  isWaitingNextPage: false,
211
211
  response,
@@ -326,9 +326,10 @@ export const createQuery = (queryFn, options = {}) => {
326
326
  useQuery.setInitialResponse = ({ key, response, skipRevalidation }) => {
327
327
  // eslint-disable-next-line react-hooks/rules-of-hooks
328
328
  useState(() => {
329
- if (response === undefined || useQuery.get(key).data)
329
+ const state = useQuery.get(key);
330
+ if (response === undefined || state.isSuccess)
330
331
  return;
331
- const newPageParam = getNextPageParam(response, 1);
332
+ const newPageParam = getNextPageParam(response, 1, state);
332
333
  useQuery.set(key, {
333
334
  status: 'success',
334
335
  isLoading: false,
@@ -1,5 +1,6 @@
1
1
  export * from './create-store';
2
2
  export * from './create-stores';
3
3
  export * from './create-query';
4
+ export * from './create-bi-direction-query';
4
5
  export * from './create-mutation';
5
6
  export * from './with-context';
@@ -1,5 +1,6 @@
1
1
  export * from './create-store';
2
2
  export * from './create-stores';
3
3
  export * from './create-query';
4
+ export * from './create-bi-direction-query';
4
5
  export * from './create-mutation';
5
6
  export * from './with-context';