@ventlio/tanstack-query 0.2.72 → 0.2.74
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 +73 -36
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +71 -8
- package/dist/index.mjs.map +1 -1
- package/dist/queries/index.d.ts +1 -0
- package/dist/queries/queries.interface.d.ts +2 -1
- package/dist/queries/useDeleteRequest.js +4 -3
- package/dist/queries/useDeleteRequest.js.map +1 -1
- package/dist/queries/useGetInfiniteRequest.d.ts +140 -0
- package/dist/queries/useGetInfiniteRequest.js +72 -0
- package/dist/queries/useGetInfiniteRequest.js.map +1 -0
- package/dist/queries/useGetRequest.js +4 -3
- package/dist/queries/useGetRequest.js.map +1 -1
- package/package.json +1 -1
- package/src/queries/index.ts +1 -0
- package/src/queries/queries.interface.ts +8 -1
- package/src/queries/useDeleteRequest.ts +7 -4
- package/src/queries/useGetInfiniteRequest.ts +121 -0
- package/src/queries/useGetRequest.ts +8 -4
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
### This is
|
|
1
|
+
### This is a complementary library that should be used with @tanstack/react-query for API REQUESTS and more
|
|
2
2
|
|
|
3
3
|
## WHY THIS PACKAGE?
|
|
4
4
|
|
|
@@ -12,12 +12,27 @@ But we were not discouraged. So, we set out to find a solution which led to the
|
|
|
12
12
|
|
|
13
13
|
> Please note that this package is still being developed and may not function as expected. We are working to refine its implementation structure to meet a functional standard. The documentation may not align with the current implementation, so if you encounter any difficulties while setting up the package, please raise an issue in the GitHub repository. We appreciate your patience and understanding as we work to improve this package.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
### Tasks
|
|
16
|
+
|
|
17
|
+
- [✅] Global settings for requests
|
|
18
|
+
- [✅] Requests context implementations
|
|
19
|
+
- [✅] Post, Get, Patch Requests
|
|
20
|
+
- [✅] Query key tracker to track dynamic query and help fetch query cache from any page
|
|
21
|
+
- [✅] Persistent queries implementation (Not completed)
|
|
22
|
+
- [❌] Put request
|
|
23
|
+
- [❌] Generic return type (this is currently an issue if the API does not return object with the necessary properties required by the library)
|
|
24
|
+
- [❌] Generic Pagination for any response without infinite queries
|
|
25
|
+
- [❌] Infinite Get Query implementation (still using implementation meant for our use case)
|
|
26
|
+
- [❌] Server sent events
|
|
27
|
+
- [❌] Socket implementations
|
|
28
|
+
- [❌] Tests
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
16
31
|
|
|
17
32
|
> You must install @tanstack/react-query and axios first to use this package
|
|
18
33
|
|
|
19
34
|
```
|
|
20
|
-
|
|
35
|
+
yarn add @tanstack/react-query axios
|
|
21
36
|
```
|
|
22
37
|
|
|
23
38
|
After that install this package
|
|
@@ -26,16 +41,41 @@ After that install this package
|
|
|
26
41
|
$ npm install @ventlio/tanstack-query
|
|
27
42
|
```
|
|
28
43
|
|
|
44
|
+
OR
|
|
45
|
+
|
|
29
46
|
```
|
|
30
47
|
$ yarn add @ventlio/tanstack-query
|
|
31
48
|
```
|
|
32
49
|
|
|
50
|
+
## CURRENT RETURN TYPE
|
|
51
|
+
|
|
52
|
+
Currently the library return type expects data structure of the below schema, so depending on the API design,
|
|
53
|
+
you can reach out to the developer to implement the return type that follows the below schema.
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
export interface IRequestError {
|
|
57
|
+
statusCode: number;
|
|
58
|
+
message: string;
|
|
59
|
+
timeStamp: Date;
|
|
60
|
+
status: boolean;
|
|
61
|
+
data?: any;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface IRequestSuccess<T> {
|
|
65
|
+
statusCode: number;
|
|
66
|
+
message: string;
|
|
67
|
+
timeStamp: Date;
|
|
68
|
+
status: boolean;
|
|
69
|
+
data: T;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
33
72
|
|
|
34
73
|
## Getting Started
|
|
35
74
|
|
|
36
75
|
Follow the below instructions to have the package running on your project
|
|
37
76
|
|
|
38
77
|
### Set the environment variables
|
|
78
|
+
|
|
39
79
|
```env
|
|
40
80
|
# For ReactJS
|
|
41
81
|
REACT_APP_API_URL='https://api.example.com'
|
|
@@ -46,6 +86,7 @@ NEXT_PUBLIC_API_URL='https://api.example.com'
|
|
|
46
86
|
NEXT_PUBLIC_API_TIMEOUT=300000
|
|
47
87
|
|
|
48
88
|
```
|
|
89
|
+
|
|
49
90
|
```js
|
|
50
91
|
import { QueryClient } from '@tanstack/react-query';
|
|
51
92
|
import { TanstackQueryConfig, bootstrapQueryRequest } from '@ventlio/tanstack-query';
|
|
@@ -56,6 +97,17 @@ const queryClient = new QueryClient();
|
|
|
56
97
|
// do this before adding the queryClient to QueryClientProvider
|
|
57
98
|
bootstrapQueryRequest(queryClient);
|
|
58
99
|
|
|
100
|
+
// recommended setup for mobile apps as the .env setup won't work
|
|
101
|
+
bootstrapQueryRequest(queryClient, {
|
|
102
|
+
context: 'app', // this is required to make the library switch to app context where necessary
|
|
103
|
+
environments: {
|
|
104
|
+
appBaseUrl: baseUrl,
|
|
105
|
+
appTimeout: 30000,
|
|
106
|
+
},
|
|
107
|
+
modelConfig: {
|
|
108
|
+
idColumn: 'id', // used for useQueryModel to uniquely identify query data in a collection/array instance
|
|
109
|
+
},
|
|
110
|
+
});
|
|
59
111
|
```
|
|
60
112
|
|
|
61
113
|
You can now use it in a QueryClientProvider
|
|
@@ -77,19 +129,17 @@ function App() {
|
|
|
77
129
|
Updating the configurations inside a component
|
|
78
130
|
|
|
79
131
|
```jsx
|
|
80
|
-
import {
|
|
81
|
-
useQueryBaseURL,
|
|
82
|
-
useQueryHeaders,
|
|
83
|
-
useQueryTimeout,
|
|
84
|
-
} from '@ventlio/tanstack-query';
|
|
132
|
+
import { useQueryBaseURL, useQueryHeaders, useQueryTimeout } from '@ventlio/tanstack-query';
|
|
85
133
|
|
|
86
134
|
function LoginPage() {
|
|
87
135
|
const { headers, setQueryHeaders } = useQueryHeaders();
|
|
88
|
-
|
|
136
|
+
const [authToken, setAuthToken] = useState();
|
|
89
137
|
useEffect(() => {
|
|
90
138
|
// after user has logged in successfully set the authorization header token
|
|
91
|
-
|
|
92
|
-
|
|
139
|
+
// this should also be done mostly in the layout that contains the authenticated views of the app
|
|
140
|
+
// for instance in AuthLayout, so that after login in the authToken can still be used to authenticate future request
|
|
141
|
+
// when user refreshes the page
|
|
142
|
+
setQueryHeaders({ Authorization: `Bearer ${authToken}` });
|
|
93
143
|
}, []);
|
|
94
144
|
|
|
95
145
|
return <>{/** codes */}</>;
|
|
@@ -133,27 +183,16 @@ The `useGetRequest` hook returns an object with the following properties:
|
|
|
133
183
|
import { useGetRequest } from '@ventlio/tanstack-query';
|
|
134
184
|
|
|
135
185
|
const MyComponent = () => {
|
|
136
|
-
const {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
page,
|
|
147
|
-
queryKey,
|
|
148
|
-
} = useGetRequest({
|
|
149
|
-
path: '/api/mydata',
|
|
150
|
-
load: true,
|
|
151
|
-
queryOptions: {
|
|
152
|
-
staleTime: 10000,
|
|
153
|
-
refetchOnWindowFocus: false,
|
|
154
|
-
},
|
|
155
|
-
keyTracker: 'mydata',
|
|
156
|
-
});
|
|
186
|
+
const { data, isLoading, isError, error, updatePath, nextPage, prevPage, get, gotoPage, page, queryKey } =
|
|
187
|
+
useGetRequest({
|
|
188
|
+
path: '/api/mydata',
|
|
189
|
+
load: true,
|
|
190
|
+
queryOptions: {
|
|
191
|
+
staleTime: 10000,
|
|
192
|
+
refetchOnWindowFocus: false,
|
|
193
|
+
},
|
|
194
|
+
keyTracker: 'mydata',
|
|
195
|
+
});
|
|
157
196
|
|
|
158
197
|
return (
|
|
159
198
|
<div>
|
|
@@ -419,8 +458,7 @@ import { useKeyTrackerModel } from '@ventlio/tanstack-query';
|
|
|
419
458
|
2. Call `useKeyTrackerModel` with a `keyTracker` parameter which is a string that uniquely identifies the query key:
|
|
420
459
|
|
|
421
460
|
```javascript
|
|
422
|
-
const { refetchQuery, getQueryKey, queryKey, data } =
|
|
423
|
-
useKeyTrackerModel < MyDataType > 'myKeyTracker';
|
|
461
|
+
const { refetchQuery, getQueryKey, queryKey, data } = useKeyTrackerModel < MyDataType > 'myKeyTracker';
|
|
424
462
|
```
|
|
425
463
|
|
|
426
464
|
3. Invoke `getQueryKey` function to retrieve the query key:
|
|
@@ -467,8 +505,7 @@ import { useKeyTrackerModel } from '@ventlio/tanstack-query';
|
|
|
467
505
|
const MyComponent = () => {
|
|
468
506
|
const queryClient = useQueryClient();
|
|
469
507
|
|
|
470
|
-
const { refetchQuery, getQueryKey, queryKey, data } =
|
|
471
|
-
useKeyTrackerModel < MyDataType > 'myKeyTracker';
|
|
508
|
+
const { refetchQuery, getQueryKey, queryKey, data } = useKeyTrackerModel < MyDataType > 'myKeyTracker';
|
|
472
509
|
|
|
473
510
|
const handleClick = async () => {
|
|
474
511
|
// Retrieve the query key
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export { useKeyTrackerModel } from './model/useKeyTrackerModel.js';
|
|
|
9
9
|
export { useQueryModel } from './model/useQueryModel.js';
|
|
10
10
|
export { useRefetchQuery } from './model/useRefetchQuery.js';
|
|
11
11
|
export { useDeleteRequest } from './queries/useDeleteRequest.js';
|
|
12
|
+
export { useGetInfiniteRequest } from './queries/useGetInfiniteRequest.js';
|
|
12
13
|
export { useGetRequest } from './queries/useGetRequest.js';
|
|
13
14
|
export { usePatchRequest } from './queries/usePatchRequest.js';
|
|
14
15
|
export { usePostRequest } from './queries/usePostRequest.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import 'url-search-params-polyfill';
|
|
2
|
-
import { useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
|
|
2
|
+
import { useQueryClient, useQuery, useInfiniteQuery, useMutation } from '@tanstack/react-query';
|
|
3
3
|
import result from 'lodash.result';
|
|
4
4
|
import lodashSet from 'lodash.set';
|
|
5
5
|
import { useState, useMemo, useEffect, startTransition } from 'react';
|
|
@@ -396,11 +396,12 @@ const useDeleteRequest = (deleteOptions) => {
|
|
|
396
396
|
const [options, setOptions] = useState();
|
|
397
397
|
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
398
398
|
const { getHeaders } = useQueryHeaders();
|
|
399
|
-
const sendRequest = async (res, rej) => {
|
|
399
|
+
const sendRequest = async (res, rej, queryKey) => {
|
|
400
400
|
// get request headers
|
|
401
401
|
const globalHeaders = getHeaders();
|
|
402
|
+
const [url] = (queryKey ?? []);
|
|
402
403
|
const postResponse = await makeRequest({
|
|
403
|
-
path: requestPath,
|
|
404
|
+
path: url ?? requestPath,
|
|
404
405
|
headers: { ...globalHeaders, ...headers },
|
|
405
406
|
method: HttpMethod.DELETE,
|
|
406
407
|
baseURL: baseUrl ?? API_URL,
|
|
@@ -413,7 +414,7 @@ const useDeleteRequest = (deleteOptions) => {
|
|
|
413
414
|
rej(postResponse);
|
|
414
415
|
}
|
|
415
416
|
};
|
|
416
|
-
const query = useQuery([requestPath, {}], () => new Promise((res, rej) => sendRequest(res, rej)), { enabled: false, ...options });
|
|
417
|
+
const query = useQuery([requestPath, {}], ({ queryKey }) => new Promise((res, rej) => sendRequest(res, rej, queryKey)), { enabled: false, ...options });
|
|
417
418
|
const updatedPathAsync = async (link) => {
|
|
418
419
|
return updateDeletePath(link);
|
|
419
420
|
};
|
|
@@ -431,6 +432,67 @@ const useDeleteRequest = (deleteOptions) => {
|
|
|
431
432
|
return { destroy, ...query };
|
|
432
433
|
};
|
|
433
434
|
|
|
435
|
+
const useGetInfiniteRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl, headers, }) => {
|
|
436
|
+
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
437
|
+
const { getHeaders } = useQueryHeaders();
|
|
438
|
+
let queryClient = useQueryClient();
|
|
439
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
440
|
+
queryClient = useMemo(() => queryClient, []);
|
|
441
|
+
const sendRequest = async (res, rej, pageParam) => {
|
|
442
|
+
if (load) {
|
|
443
|
+
// get request headers
|
|
444
|
+
const globalHeaders = getHeaders();
|
|
445
|
+
const getResponse = await makeRequest({
|
|
446
|
+
path: pageParam ?? path,
|
|
447
|
+
headers: { ...globalHeaders, ...headers },
|
|
448
|
+
baseURL: baseUrl ?? API_URL,
|
|
449
|
+
timeout: TIMEOUT,
|
|
450
|
+
});
|
|
451
|
+
if (getResponse.status) {
|
|
452
|
+
res(getResponse);
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
rej(getResponse);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
res(null);
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
const query = useInfiniteQuery([path, {}], ({ pageParam = path }) => new Promise((res, rej) => sendRequest(res, rej, pageParam)), {
|
|
463
|
+
enabled: load,
|
|
464
|
+
getNextPageParam: (lastPage, pages) => constructPaginationLink('next_page', lastPage, pages),
|
|
465
|
+
getPreviousPageParam: (lastPage, pages) => constructPaginationLink('previous_page', lastPage, pages),
|
|
466
|
+
...queryOptions,
|
|
467
|
+
});
|
|
468
|
+
/**
|
|
469
|
+
*
|
|
470
|
+
* This pagination implementation is currently tied to our use case
|
|
471
|
+
*/
|
|
472
|
+
const constructPaginationLink = (direction, lastPage, pages) => {
|
|
473
|
+
const [pathname, queryString] = lastPage.split('?');
|
|
474
|
+
const queryParams = new URLSearchParams(queryString);
|
|
475
|
+
const lastPageItem = pages[pages.length - 1];
|
|
476
|
+
queryParams.set('page', String(lastPageItem?.data.pagination[direction]));
|
|
477
|
+
return pathname + '?' + queryParams.toString();
|
|
478
|
+
};
|
|
479
|
+
useEffect(() => {
|
|
480
|
+
if (keyTracker) {
|
|
481
|
+
// set expiration time for the tracker
|
|
482
|
+
queryClient.setQueryDefaults([keyTracker], {
|
|
483
|
+
cacheTime: Infinity,
|
|
484
|
+
staleTime: Infinity,
|
|
485
|
+
});
|
|
486
|
+
queryClient.setQueryData([keyTracker], [path, {}]);
|
|
487
|
+
}
|
|
488
|
+
}, [keyTracker, path, queryClient, queryOptions?.staleTime]);
|
|
489
|
+
const flattenedData = query.data?.pages.flat() ?? [];
|
|
490
|
+
return {
|
|
491
|
+
...query,
|
|
492
|
+
flattenedData,
|
|
493
|
+
};
|
|
494
|
+
};
|
|
495
|
+
|
|
434
496
|
const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl, headers, }) => {
|
|
435
497
|
const [requestPath, updatePath] = useState(path);
|
|
436
498
|
const [options, setOptions] = useState(queryOptions);
|
|
@@ -440,12 +502,13 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
|
|
|
440
502
|
let queryClient = useQueryClient();
|
|
441
503
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
442
504
|
queryClient = useMemo(() => queryClient, []);
|
|
443
|
-
const sendRequest = async (res, rej) => {
|
|
505
|
+
const sendRequest = async (res, rej, queryKey) => {
|
|
444
506
|
if (load) {
|
|
445
507
|
// get request headers
|
|
446
508
|
const globalHeaders = getHeaders();
|
|
509
|
+
const [url] = (queryKey ?? []);
|
|
447
510
|
const getResponse = await makeRequest({
|
|
448
|
-
path: requestPath,
|
|
511
|
+
path: url ?? requestPath,
|
|
449
512
|
headers: { ...globalHeaders, ...headers },
|
|
450
513
|
baseURL: baseUrl ?? API_URL,
|
|
451
514
|
timeout: TIMEOUT,
|
|
@@ -461,7 +524,7 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
|
|
|
461
524
|
res(null);
|
|
462
525
|
}
|
|
463
526
|
};
|
|
464
|
-
const query = useQuery([requestPath, {}], () => new Promise((res, rej) => sendRequest(res, rej)), {
|
|
527
|
+
const query = useQuery([requestPath, {}], ({ queryKey }) => new Promise((res, rej) => sendRequest(res, rej, queryKey)), {
|
|
465
528
|
enabled: load,
|
|
466
529
|
...options,
|
|
467
530
|
});
|
|
@@ -624,5 +687,5 @@ const usePostRequest = ({ path, isFormData = false, baseUrl, headers, fileSelect
|
|
|
624
687
|
return { post, ...mutation };
|
|
625
688
|
};
|
|
626
689
|
|
|
627
|
-
export { ContentType, HttpMethod, axiosInstance, bootstrapQueryRequest, buildFormData, errorTransformer, getDateInFuture, makeRequest, scrollToTop, successTransformer, useDeleteRequest, useEnvironmentVariables, useGetRequest, useKeyTrackerModel, usePatchRequest, usePostRequest, useQueryConfig, useQueryHeaders, useQueryModel, useReactNativeEnv, useRefetchQuery };
|
|
690
|
+
export { ContentType, HttpMethod, axiosInstance, bootstrapQueryRequest, buildFormData, errorTransformer, getDateInFuture, makeRequest, scrollToTop, successTransformer, useDeleteRequest, useEnvironmentVariables, useGetInfiniteRequest, useGetRequest, useKeyTrackerModel, usePatchRequest, usePostRequest, useQueryConfig, useQueryHeaders, useQueryModel, useReactNativeEnv, useRefetchQuery };
|
|
628
691
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/queries/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { UseQueryOptions } from '@tanstack/react-query';
|
|
1
|
+
import type { UseInfiniteQueryOptions, UseQueryOptions } from '@tanstack/react-query';
|
|
2
2
|
import type { RawAxiosRequestHeaders } from 'axios';
|
|
3
3
|
import type { IRequestError, IRequestSuccess } from '../request';
|
|
4
4
|
export interface IPagination {
|
|
@@ -10,6 +10,7 @@ export interface IPagination {
|
|
|
10
10
|
total: number;
|
|
11
11
|
}
|
|
12
12
|
export type TanstackQueryOption<TResponse> = UseQueryOptions<IRequestSuccess<TResponse | undefined>, IRequestError, IRequestSuccess<TResponse | undefined>, Array<any>>;
|
|
13
|
+
export type TanstackInfiniteQueryOption<TResponse> = UseInfiniteQueryOptions<IRequestSuccess<TResponse | undefined>, IRequestError, IRequestSuccess<TResponse | undefined>, Array<any>>;
|
|
13
14
|
export interface DefaultRequestOptions {
|
|
14
15
|
baseUrl?: string;
|
|
15
16
|
headers?: RawAxiosRequestHeaders;
|
|
@@ -13,11 +13,12 @@ const useDeleteRequest = (deleteOptions) => {
|
|
|
13
13
|
const [options, setOptions] = useState();
|
|
14
14
|
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
15
15
|
const { getHeaders } = useQueryHeaders();
|
|
16
|
-
const sendRequest = async (res, rej) => {
|
|
16
|
+
const sendRequest = async (res, rej, queryKey) => {
|
|
17
17
|
// get request headers
|
|
18
18
|
const globalHeaders = getHeaders();
|
|
19
|
+
const [url] = (queryKey ?? []);
|
|
19
20
|
const postResponse = await makeRequest({
|
|
20
|
-
path: requestPath,
|
|
21
|
+
path: url ?? requestPath,
|
|
21
22
|
headers: { ...globalHeaders, ...headers },
|
|
22
23
|
method: HttpMethod.DELETE,
|
|
23
24
|
baseURL: baseUrl ?? API_URL,
|
|
@@ -30,7 +31,7 @@ const useDeleteRequest = (deleteOptions) => {
|
|
|
30
31
|
rej(postResponse);
|
|
31
32
|
}
|
|
32
33
|
};
|
|
33
|
-
const query = useQuery([requestPath, {}], () => new Promise((res, rej) => sendRequest(res, rej)), { enabled: false, ...options });
|
|
34
|
+
const query = useQuery([requestPath, {}], ({ queryKey }) => new Promise((res, rej) => sendRequest(res, rej, queryKey)), { enabled: false, ...options });
|
|
34
35
|
const updatedPathAsync = async (link) => {
|
|
35
36
|
return updateDeletePath(link);
|
|
36
37
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDeleteRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useDeleteRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { IRequestSuccess } from '../request';
|
|
2
|
+
import type { DefaultRequestOptions, TanstackInfiniteQueryOption } from './queries.interface';
|
|
3
|
+
export declare const useGetInfiniteRequest: <TResponse extends Record<string, any>>({ path, load, queryOptions, keyTracker, baseUrl, headers, }: {
|
|
4
|
+
path: string;
|
|
5
|
+
load?: boolean | undefined;
|
|
6
|
+
queryOptions?: TanstackInfiniteQueryOption<TResponse> | undefined;
|
|
7
|
+
keyTracker?: string | undefined;
|
|
8
|
+
} & DefaultRequestOptions) => {
|
|
9
|
+
flattenedData: IRequestSuccess<TResponse>[];
|
|
10
|
+
data: undefined;
|
|
11
|
+
error: any;
|
|
12
|
+
isError: true;
|
|
13
|
+
isLoading: false;
|
|
14
|
+
isLoadingError: true;
|
|
15
|
+
isRefetchError: false;
|
|
16
|
+
isSuccess: false;
|
|
17
|
+
status: "error";
|
|
18
|
+
fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
|
|
19
|
+
fetchPreviousPage: (options?: import("@tanstack/react-query").FetchPreviousPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
|
|
20
|
+
hasNextPage?: boolean | undefined;
|
|
21
|
+
hasPreviousPage?: boolean | undefined;
|
|
22
|
+
isFetchingNextPage: boolean;
|
|
23
|
+
isFetchingPreviousPage: boolean;
|
|
24
|
+
dataUpdatedAt: number;
|
|
25
|
+
errorUpdatedAt: number;
|
|
26
|
+
failureCount: number;
|
|
27
|
+
failureReason: any;
|
|
28
|
+
errorUpdateCount: number;
|
|
29
|
+
isFetched: boolean;
|
|
30
|
+
isFetchedAfterMount: boolean;
|
|
31
|
+
isFetching: boolean;
|
|
32
|
+
isInitialLoading: boolean;
|
|
33
|
+
isPaused: boolean;
|
|
34
|
+
isPlaceholderData: boolean;
|
|
35
|
+
isPreviousData: boolean;
|
|
36
|
+
isRefetching: boolean;
|
|
37
|
+
isStale: boolean;
|
|
38
|
+
refetch: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>, any>>;
|
|
39
|
+
remove: () => void;
|
|
40
|
+
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
41
|
+
} | {
|
|
42
|
+
flattenedData: IRequestSuccess<TResponse>[];
|
|
43
|
+
data: undefined;
|
|
44
|
+
error: null;
|
|
45
|
+
isError: false;
|
|
46
|
+
isLoading: true;
|
|
47
|
+
isLoadingError: false;
|
|
48
|
+
isRefetchError: false;
|
|
49
|
+
isSuccess: false;
|
|
50
|
+
status: "loading";
|
|
51
|
+
fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
|
|
52
|
+
fetchPreviousPage: (options?: import("@tanstack/react-query").FetchPreviousPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
|
|
53
|
+
hasNextPage?: boolean | undefined;
|
|
54
|
+
hasPreviousPage?: boolean | undefined;
|
|
55
|
+
isFetchingNextPage: boolean;
|
|
56
|
+
isFetchingPreviousPage: boolean;
|
|
57
|
+
dataUpdatedAt: number;
|
|
58
|
+
errorUpdatedAt: number;
|
|
59
|
+
failureCount: number;
|
|
60
|
+
failureReason: any;
|
|
61
|
+
errorUpdateCount: number;
|
|
62
|
+
isFetched: boolean;
|
|
63
|
+
isFetchedAfterMount: boolean;
|
|
64
|
+
isFetching: boolean;
|
|
65
|
+
isInitialLoading: boolean;
|
|
66
|
+
isPaused: boolean;
|
|
67
|
+
isPlaceholderData: boolean;
|
|
68
|
+
isPreviousData: boolean;
|
|
69
|
+
isRefetching: boolean;
|
|
70
|
+
isStale: boolean;
|
|
71
|
+
refetch: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>, any>>;
|
|
72
|
+
remove: () => void;
|
|
73
|
+
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
74
|
+
} | {
|
|
75
|
+
flattenedData: IRequestSuccess<TResponse>[];
|
|
76
|
+
data: import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>;
|
|
77
|
+
error: any;
|
|
78
|
+
isError: true;
|
|
79
|
+
isLoading: false;
|
|
80
|
+
isLoadingError: false;
|
|
81
|
+
isRefetchError: true;
|
|
82
|
+
isSuccess: false;
|
|
83
|
+
status: "error";
|
|
84
|
+
fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
|
|
85
|
+
fetchPreviousPage: (options?: import("@tanstack/react-query").FetchPreviousPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
|
|
86
|
+
hasNextPage?: boolean | undefined;
|
|
87
|
+
hasPreviousPage?: boolean | undefined;
|
|
88
|
+
isFetchingNextPage: boolean;
|
|
89
|
+
isFetchingPreviousPage: boolean;
|
|
90
|
+
dataUpdatedAt: number;
|
|
91
|
+
errorUpdatedAt: number;
|
|
92
|
+
failureCount: number;
|
|
93
|
+
failureReason: any;
|
|
94
|
+
errorUpdateCount: number;
|
|
95
|
+
isFetched: boolean;
|
|
96
|
+
isFetchedAfterMount: boolean;
|
|
97
|
+
isFetching: boolean;
|
|
98
|
+
isInitialLoading: boolean;
|
|
99
|
+
isPaused: boolean;
|
|
100
|
+
isPlaceholderData: boolean;
|
|
101
|
+
isPreviousData: boolean;
|
|
102
|
+
isRefetching: boolean;
|
|
103
|
+
isStale: boolean;
|
|
104
|
+
refetch: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>, any>>;
|
|
105
|
+
remove: () => void;
|
|
106
|
+
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
107
|
+
} | {
|
|
108
|
+
flattenedData: IRequestSuccess<TResponse>[];
|
|
109
|
+
data: import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>;
|
|
110
|
+
error: null;
|
|
111
|
+
isError: false;
|
|
112
|
+
isLoading: false;
|
|
113
|
+
isLoadingError: false;
|
|
114
|
+
isRefetchError: false;
|
|
115
|
+
isSuccess: true;
|
|
116
|
+
status: "success";
|
|
117
|
+
fetchNextPage: (options?: import("@tanstack/react-query").FetchNextPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
|
|
118
|
+
fetchPreviousPage: (options?: import("@tanstack/react-query").FetchPreviousPageOptions | undefined) => Promise<import("@tanstack/react-query").InfiniteQueryObserverResult<IRequestSuccess<TResponse>, any>>;
|
|
119
|
+
hasNextPage?: boolean | undefined;
|
|
120
|
+
hasPreviousPage?: boolean | undefined;
|
|
121
|
+
isFetchingNextPage: boolean;
|
|
122
|
+
isFetchingPreviousPage: boolean;
|
|
123
|
+
dataUpdatedAt: number;
|
|
124
|
+
errorUpdatedAt: number;
|
|
125
|
+
failureCount: number;
|
|
126
|
+
failureReason: any;
|
|
127
|
+
errorUpdateCount: number;
|
|
128
|
+
isFetched: boolean;
|
|
129
|
+
isFetchedAfterMount: boolean;
|
|
130
|
+
isFetching: boolean;
|
|
131
|
+
isInitialLoading: boolean;
|
|
132
|
+
isPaused: boolean;
|
|
133
|
+
isPlaceholderData: boolean;
|
|
134
|
+
isPreviousData: boolean;
|
|
135
|
+
isRefetching: boolean;
|
|
136
|
+
isStale: boolean;
|
|
137
|
+
refetch: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<import("@tanstack/react-query").InfiniteData<IRequestSuccess<TResponse>>, any>>;
|
|
138
|
+
remove: () => void;
|
|
139
|
+
fetchStatus: import("@tanstack/react-query").FetchStatus;
|
|
140
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useQueryClient, useInfiniteQuery } from '@tanstack/react-query';
|
|
2
|
+
import { useMemo, useEffect } from 'react';
|
|
3
|
+
import 'url-search-params-polyfill';
|
|
4
|
+
import { useEnvironmentVariables } from '../config/useEnvironmentVariables.js';
|
|
5
|
+
import { useQueryHeaders } from '../config/useQueryHeaders.js';
|
|
6
|
+
import 'axios';
|
|
7
|
+
import { makeRequest } from '../request/make-request.js';
|
|
8
|
+
import '../request/request.enum.js';
|
|
9
|
+
|
|
10
|
+
const useGetInfiniteRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl, headers, }) => {
|
|
11
|
+
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
12
|
+
const { getHeaders } = useQueryHeaders();
|
|
13
|
+
let queryClient = useQueryClient();
|
|
14
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
15
|
+
queryClient = useMemo(() => queryClient, []);
|
|
16
|
+
const sendRequest = async (res, rej, pageParam) => {
|
|
17
|
+
if (load) {
|
|
18
|
+
// get request headers
|
|
19
|
+
const globalHeaders = getHeaders();
|
|
20
|
+
const getResponse = await makeRequest({
|
|
21
|
+
path: pageParam ?? path,
|
|
22
|
+
headers: { ...globalHeaders, ...headers },
|
|
23
|
+
baseURL: baseUrl ?? API_URL,
|
|
24
|
+
timeout: TIMEOUT,
|
|
25
|
+
});
|
|
26
|
+
if (getResponse.status) {
|
|
27
|
+
res(getResponse);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
rej(getResponse);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
res(null);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const query = useInfiniteQuery([path, {}], ({ pageParam = path }) => new Promise((res, rej) => sendRequest(res, rej, pageParam)), {
|
|
38
|
+
enabled: load,
|
|
39
|
+
getNextPageParam: (lastPage, pages) => constructPaginationLink('next_page', lastPage, pages),
|
|
40
|
+
getPreviousPageParam: (lastPage, pages) => constructPaginationLink('previous_page', lastPage, pages),
|
|
41
|
+
...queryOptions,
|
|
42
|
+
});
|
|
43
|
+
/**
|
|
44
|
+
*
|
|
45
|
+
* This pagination implementation is currently tied to our use case
|
|
46
|
+
*/
|
|
47
|
+
const constructPaginationLink = (direction, lastPage, pages) => {
|
|
48
|
+
const [pathname, queryString] = lastPage.split('?');
|
|
49
|
+
const queryParams = new URLSearchParams(queryString);
|
|
50
|
+
const lastPageItem = pages[pages.length - 1];
|
|
51
|
+
queryParams.set('page', String(lastPageItem?.data.pagination[direction]));
|
|
52
|
+
return pathname + '?' + queryParams.toString();
|
|
53
|
+
};
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (keyTracker) {
|
|
56
|
+
// set expiration time for the tracker
|
|
57
|
+
queryClient.setQueryDefaults([keyTracker], {
|
|
58
|
+
cacheTime: Infinity,
|
|
59
|
+
staleTime: Infinity,
|
|
60
|
+
});
|
|
61
|
+
queryClient.setQueryData([keyTracker], [path, {}]);
|
|
62
|
+
}
|
|
63
|
+
}, [keyTracker, path, queryClient, queryOptions?.staleTime]);
|
|
64
|
+
const flattenedData = query.data?.pages.flat() ?? [];
|
|
65
|
+
return {
|
|
66
|
+
...query,
|
|
67
|
+
flattenedData,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export { useGetInfiniteRequest };
|
|
72
|
+
//# sourceMappingURL=useGetInfiniteRequest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGetInfiniteRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -16,12 +16,13 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
|
|
|
16
16
|
let queryClient = useQueryClient();
|
|
17
17
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
18
18
|
queryClient = useMemo(() => queryClient, []);
|
|
19
|
-
const sendRequest = async (res, rej) => {
|
|
19
|
+
const sendRequest = async (res, rej, queryKey) => {
|
|
20
20
|
if (load) {
|
|
21
21
|
// get request headers
|
|
22
22
|
const globalHeaders = getHeaders();
|
|
23
|
+
const [url] = (queryKey ?? []);
|
|
23
24
|
const getResponse = await makeRequest({
|
|
24
|
-
path: requestPath,
|
|
25
|
+
path: url ?? requestPath,
|
|
25
26
|
headers: { ...globalHeaders, ...headers },
|
|
26
27
|
baseURL: baseUrl ?? API_URL,
|
|
27
28
|
timeout: TIMEOUT,
|
|
@@ -37,7 +38,7 @@ const useGetRequest = ({ path, load = false, queryOptions, keyTracker, baseUrl,
|
|
|
37
38
|
res(null);
|
|
38
39
|
}
|
|
39
40
|
};
|
|
40
|
-
const query = useQuery([requestPath, {}], () => new Promise((res, rej) => sendRequest(res, rej)), {
|
|
41
|
+
const query = useQuery([requestPath, {}], ({ queryKey }) => new Promise((res, rej) => sendRequest(res, rej, queryKey)), {
|
|
41
42
|
enabled: load,
|
|
42
43
|
...options,
|
|
43
44
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGetRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useGetRequest.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
package/src/queries/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { UseQueryOptions } from '@tanstack/react-query';
|
|
1
|
+
import type { UseInfiniteQueryOptions, UseQueryOptions } from '@tanstack/react-query';
|
|
2
2
|
import type { RawAxiosRequestHeaders } from 'axios';
|
|
3
3
|
import type { IRequestError, IRequestSuccess } from '../request';
|
|
4
4
|
|
|
@@ -18,6 +18,13 @@ export type TanstackQueryOption<TResponse> = UseQueryOptions<
|
|
|
18
18
|
Array<any>
|
|
19
19
|
>;
|
|
20
20
|
|
|
21
|
+
export type TanstackInfiniteQueryOption<TResponse> = UseInfiniteQueryOptions<
|
|
22
|
+
IRequestSuccess<TResponse | undefined>,
|
|
23
|
+
IRequestError,
|
|
24
|
+
IRequestSuccess<TResponse | undefined>,
|
|
25
|
+
Array<any>
|
|
26
|
+
>;
|
|
27
|
+
|
|
21
28
|
export interface DefaultRequestOptions {
|
|
22
29
|
baseUrl?: string;
|
|
23
30
|
headers?: RawAxiosRequestHeaders;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { UseQueryOptions } from '@tanstack/react-query';
|
|
1
|
+
import type { QueryKey, UseQueryOptions } from '@tanstack/react-query';
|
|
2
2
|
import { useQuery } from '@tanstack/react-query';
|
|
3
3
|
import type { RawAxiosRequestHeaders } from 'axios';
|
|
4
4
|
import { useState } from 'react';
|
|
@@ -16,12 +16,14 @@ export const useDeleteRequest = <TResponse>(deleteOptions?: DefaultRequestOption
|
|
|
16
16
|
|
|
17
17
|
const { getHeaders } = useQueryHeaders();
|
|
18
18
|
|
|
19
|
-
const sendRequest = async (res: (value: any) => void, rej: (reason?: any) => void) => {
|
|
19
|
+
const sendRequest = async (res: (value: any) => void, rej: (reason?: any) => void, queryKey?: QueryKey) => {
|
|
20
20
|
// get request headers
|
|
21
21
|
const globalHeaders: RawAxiosRequestHeaders = getHeaders();
|
|
22
22
|
|
|
23
|
+
const [url] = (queryKey ?? []) as string[];
|
|
24
|
+
|
|
23
25
|
const postResponse = await makeRequest<TResponse>({
|
|
24
|
-
path: requestPath,
|
|
26
|
+
path: url ?? requestPath,
|
|
25
27
|
headers: { ...globalHeaders, ...headers },
|
|
26
28
|
method: HttpMethod.DELETE,
|
|
27
29
|
baseURL: baseUrl ?? API_URL,
|
|
@@ -37,7 +39,8 @@ export const useDeleteRequest = <TResponse>(deleteOptions?: DefaultRequestOption
|
|
|
37
39
|
|
|
38
40
|
const query = useQuery<any, any, IRequestSuccess<TResponse>>(
|
|
39
41
|
[requestPath, {}],
|
|
40
|
-
(
|
|
42
|
+
({ queryKey }) =>
|
|
43
|
+
new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej, queryKey)),
|
|
41
44
|
{ enabled: false, ...options }
|
|
42
45
|
);
|
|
43
46
|
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { useInfiniteQuery, useQueryClient } from '@tanstack/react-query';
|
|
2
|
+
import type { RawAxiosRequestHeaders } from 'axios';
|
|
3
|
+
import { useEffect, useMemo } from 'react';
|
|
4
|
+
import { useEnvironmentVariables, useQueryHeaders } from '../config';
|
|
5
|
+
|
|
6
|
+
import type { IRequestError, IRequestSuccess } from '../request';
|
|
7
|
+
import { makeRequest } from '../request';
|
|
8
|
+
import type { DefaultRequestOptions, TanstackInfiniteQueryOption } from './queries.interface';
|
|
9
|
+
|
|
10
|
+
interface Pagination {
|
|
11
|
+
previous_page: number;
|
|
12
|
+
current_page: number;
|
|
13
|
+
next_page: number;
|
|
14
|
+
size: number;
|
|
15
|
+
page_count: number;
|
|
16
|
+
total: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const useGetInfiniteRequest = <TResponse extends Record<string, any>>({
|
|
20
|
+
path,
|
|
21
|
+
load = false,
|
|
22
|
+
queryOptions,
|
|
23
|
+
keyTracker,
|
|
24
|
+
baseUrl,
|
|
25
|
+
headers,
|
|
26
|
+
}: {
|
|
27
|
+
path: string;
|
|
28
|
+
load?: boolean;
|
|
29
|
+
queryOptions?: TanstackInfiniteQueryOption<TResponse>;
|
|
30
|
+
keyTracker?: string;
|
|
31
|
+
} & DefaultRequestOptions) => {
|
|
32
|
+
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
33
|
+
const { getHeaders } = useQueryHeaders();
|
|
34
|
+
|
|
35
|
+
let queryClient = useQueryClient();
|
|
36
|
+
|
|
37
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
38
|
+
queryClient = useMemo(() => queryClient, []);
|
|
39
|
+
|
|
40
|
+
const sendRequest = async (
|
|
41
|
+
res: (
|
|
42
|
+
value: IRequestError | IRequestSuccess<TResponse> | PromiseLike<IRequestError | IRequestSuccess<TResponse>>
|
|
43
|
+
) => void,
|
|
44
|
+
rej: (reason?: any) => void,
|
|
45
|
+
pageParam?: string
|
|
46
|
+
) => {
|
|
47
|
+
if (load) {
|
|
48
|
+
// get request headers
|
|
49
|
+
const globalHeaders: RawAxiosRequestHeaders = getHeaders();
|
|
50
|
+
|
|
51
|
+
const getResponse = await makeRequest<TResponse>({
|
|
52
|
+
path: pageParam ?? path,
|
|
53
|
+
headers: { ...globalHeaders, ...headers },
|
|
54
|
+
baseURL: baseUrl ?? API_URL,
|
|
55
|
+
timeout: TIMEOUT,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (getResponse.status) {
|
|
59
|
+
res(getResponse as IRequestSuccess<TResponse>);
|
|
60
|
+
} else {
|
|
61
|
+
rej(getResponse);
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
res(null as any);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const query = useInfiniteQuery<any, any, IRequestSuccess<TResponse>>(
|
|
69
|
+
[path, {}],
|
|
70
|
+
({ pageParam = path }) =>
|
|
71
|
+
new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej, pageParam)),
|
|
72
|
+
{
|
|
73
|
+
enabled: load,
|
|
74
|
+
getNextPageParam: (lastPage, pages) => constructPaginationLink('next_page', lastPage, pages),
|
|
75
|
+
getPreviousPageParam: (lastPage, pages) => constructPaginationLink('previous_page', lastPage, pages),
|
|
76
|
+
...(queryOptions as any),
|
|
77
|
+
}
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
*
|
|
82
|
+
* This pagination implementation is currently tied to our use case
|
|
83
|
+
*/
|
|
84
|
+
const constructPaginationLink = (
|
|
85
|
+
direction: 'next_page' | 'previous_page',
|
|
86
|
+
lastPage: string,
|
|
87
|
+
pages: IRequestSuccess<
|
|
88
|
+
TResponse & {
|
|
89
|
+
pagination: Pagination;
|
|
90
|
+
}
|
|
91
|
+
>[]
|
|
92
|
+
) => {
|
|
93
|
+
const [pathname, queryString] = lastPage.split('?');
|
|
94
|
+
|
|
95
|
+
const queryParams = new URLSearchParams(queryString);
|
|
96
|
+
const lastPageItem = pages[pages.length - 1];
|
|
97
|
+
|
|
98
|
+
queryParams.set('page', String(lastPageItem?.data.pagination[direction]));
|
|
99
|
+
|
|
100
|
+
return pathname + '?' + queryParams.toString();
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (keyTracker) {
|
|
105
|
+
// set expiration time for the tracker
|
|
106
|
+
queryClient.setQueryDefaults([keyTracker], {
|
|
107
|
+
cacheTime: Infinity,
|
|
108
|
+
staleTime: Infinity,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
queryClient.setQueryData([keyTracker], [path, {}]);
|
|
112
|
+
}
|
|
113
|
+
}, [keyTracker, path, queryClient, queryOptions?.staleTime]);
|
|
114
|
+
|
|
115
|
+
const flattenedData = query.data?.pages.flat() ?? [];
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
...query,
|
|
119
|
+
flattenedData,
|
|
120
|
+
};
|
|
121
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { UseQueryOptions } from '@tanstack/react-query';
|
|
1
|
+
import type { QueryKey, UseQueryOptions } from '@tanstack/react-query';
|
|
2
2
|
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
3
3
|
import { startTransition, useEffect, useMemo, useState } from 'react';
|
|
4
4
|
import type { RawAxiosRequestHeaders } from '../../node_modules/axios/index';
|
|
@@ -37,14 +37,17 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
|
|
|
37
37
|
res: (
|
|
38
38
|
value: IRequestError | IRequestSuccess<TResponse> | PromiseLike<IRequestError | IRequestSuccess<TResponse>>
|
|
39
39
|
) => void,
|
|
40
|
-
rej: (reason?: any) => void
|
|
40
|
+
rej: (reason?: any) => void,
|
|
41
|
+
queryKey?: QueryKey
|
|
41
42
|
) => {
|
|
42
43
|
if (load) {
|
|
43
44
|
// get request headers
|
|
44
45
|
const globalHeaders: RawAxiosRequestHeaders = getHeaders();
|
|
45
46
|
|
|
47
|
+
const [url] = (queryKey ?? []) as string[];
|
|
48
|
+
|
|
46
49
|
const getResponse = await makeRequest<TResponse>({
|
|
47
|
-
path: requestPath,
|
|
50
|
+
path: url ?? requestPath,
|
|
48
51
|
headers: { ...globalHeaders, ...headers },
|
|
49
52
|
baseURL: baseUrl ?? API_URL,
|
|
50
53
|
timeout: TIMEOUT,
|
|
@@ -62,7 +65,8 @@ export const useGetRequest = <TResponse extends Record<string, any>>({
|
|
|
62
65
|
|
|
63
66
|
const query = useQuery<any, any, IRequestSuccess<TResponse>>(
|
|
64
67
|
[requestPath, {}],
|
|
65
|
-
(
|
|
68
|
+
({ queryKey }) =>
|
|
69
|
+
new Promise<IRequestSuccess<TResponse> | IRequestError>((res, rej) => sendRequest(res, rej, queryKey)),
|
|
66
70
|
{
|
|
67
71
|
enabled: load,
|
|
68
72
|
...options,
|