@ventlio/tanstack-query 0.3.1 → 0.3.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/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +127 -33
- package/dist/index.mjs.map +1 -1
- package/dist/queries/useDeleteRequest.d.ts +4 -4
- package/dist/queries/useDeleteRequest.js +26 -9
- package/dist/queries/useDeleteRequest.js.map +1 -1
- package/dist/queries/useGetInfiniteRequest.d.ts +4 -4
- package/dist/queries/useGetInfiniteRequest.js +21 -4
- package/dist/queries/useGetInfiniteRequest.js.map +1 -1
- package/dist/queries/useGetRequest.d.ts +4 -4
- package/dist/queries/useGetRequest.js +21 -4
- package/dist/queries/useGetRequest.js.map +1 -1
- package/dist/queries/usePatchRequest.d.ts +8 -8
- package/dist/queries/usePatchRequest.js +19 -2
- package/dist/queries/usePatchRequest.js.map +1 -1
- package/dist/queries/usePostRequest.d.ts +8 -8
- package/dist/queries/usePostRequest.js +20 -3
- package/dist/queries/usePostRequest.js.map +1 -1
- package/dist/stores/index.d.ts +1 -0
- package/dist/stores/usePauseFutureRequests.d.ts +7 -0
- package/dist/stores/usePauseFutureRequests.js +19 -0
- package/dist/stores/usePauseFutureRequests.js.map +1 -0
- package/package.json +4 -2
- package/src/__tests__/queries/usePostRequest.spec.tsx +84 -0
- package/src/index.ts +2 -0
- package/src/queries/useDeleteRequest.ts +27 -9
- package/src/queries/useGetInfiniteRequest.ts +22 -4
- package/src/queries/useGetRequest.ts +22 -4
- package/src/queries/usePatchRequest.ts +22 -3
- package/src/queries/usePostRequest.ts +22 -4
- package/src/stores/index.ts +1 -0
- package/src/stores/usePauseFutureRequests.ts +25 -0
- package/src/__tests__/queries/usePostRequest.spec.ts +0 -77
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import type { MutateOptions } from '@tanstack/react-query';
|
|
2
2
|
import { useMutation } from '@tanstack/react-query';
|
|
3
3
|
import type { RawAxiosRequestHeaders } from 'axios';
|
|
4
|
+
import { useEffect, useState } from 'react';
|
|
4
5
|
import { useEnvironmentVariables, useQueryConfig, useQueryHeaders } from '../config';
|
|
5
6
|
import { scrollToTop } from '../helpers';
|
|
6
7
|
import { useUploadProgress } from '../hooks';
|
|
7
8
|
import { HttpMethod, makeRequest } from '../request';
|
|
8
9
|
import type { IRequestError, IRequestSuccess } from '../request/request.interface';
|
|
10
|
+
import { usePauseFutureRequests } from '../stores';
|
|
9
11
|
import type { DefaultRequestOptions } from './queries.interface';
|
|
10
12
|
|
|
11
13
|
export const usePatchRequest = <TResponse>({ path, baseUrl, headers }: { path: string } & DefaultRequestOptions) => {
|
|
12
14
|
const { API_URL, TIMEOUT } = useEnvironmentVariables();
|
|
13
15
|
const { uploadProgressPercent, onUploadProgress } = useUploadProgress();
|
|
14
16
|
|
|
17
|
+
const [requestPayload, setRequestPayload] = useState<Record<any, any>>();
|
|
18
|
+
|
|
19
|
+
const isFutureMutationsPaused = usePauseFutureRequests((state) => state.isFutureMutationsPaused);
|
|
20
|
+
|
|
15
21
|
const { getHeaders } = useQueryHeaders();
|
|
16
22
|
|
|
17
23
|
const config = useQueryConfig();
|
|
@@ -71,9 +77,22 @@ export const usePatchRequest = <TResponse>({ path, baseUrl, headers }: { path: s
|
|
|
71
77
|
const patch = async (
|
|
72
78
|
data: any,
|
|
73
79
|
options?: MutateOptions<IRequestSuccess<TResponse>, IRequestError, void, unknown> | undefined
|
|
74
|
-
): Promise<IRequestSuccess<TResponse
|
|
75
|
-
|
|
80
|
+
): Promise<IRequestSuccess<TResponse> | undefined> => {
|
|
81
|
+
if (!isFutureMutationsPaused) {
|
|
82
|
+
return mutation.mutateAsync(data, options);
|
|
83
|
+
} else {
|
|
84
|
+
setRequestPayload({ data, options });
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
76
87
|
};
|
|
77
88
|
|
|
78
|
-
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
if (!isFutureMutationsPaused && requestPayload) {
|
|
91
|
+
patch(requestPayload.data, requestPayload.options);
|
|
92
|
+
setRequestPayload(undefined);
|
|
93
|
+
}
|
|
94
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
95
|
+
}, [isFutureMutationsPaused]);
|
|
96
|
+
|
|
97
|
+
return { patch, uploadProgressPercent, ...mutation, isLoading: mutation.isLoading || isFutureMutationsPaused };
|
|
79
98
|
};
|
|
@@ -3,10 +3,12 @@ import { useMutation } from '@tanstack/react-query';
|
|
|
3
3
|
import { useEnvironmentVariables, useQueryConfig, useQueryHeaders, useReactNativeEnv } from '../config';
|
|
4
4
|
|
|
5
5
|
import type { RawAxiosRequestHeaders } from 'axios';
|
|
6
|
+
import { useEffect, useState } from 'react';
|
|
6
7
|
import { scrollToTop } from '../helpers';
|
|
7
8
|
import { useUploadProgress } from '../hooks';
|
|
8
9
|
import type { IMakeRequest, IRequestError, IRequestSuccess } from '../request';
|
|
9
10
|
import { HttpMethod, makeRequest } from '../request';
|
|
11
|
+
import { usePauseFutureRequests } from '../stores';
|
|
10
12
|
import type { DefaultRequestOptions } from './queries.interface';
|
|
11
13
|
|
|
12
14
|
export const usePostRequest = <TResponse>({
|
|
@@ -27,6 +29,9 @@ export const usePostRequest = <TResponse>({
|
|
|
27
29
|
const { getHeaders } = useQueryHeaders();
|
|
28
30
|
const { isApp } = useReactNativeEnv();
|
|
29
31
|
const { uploadProgressPercent, onUploadProgress } = useUploadProgress();
|
|
32
|
+
const [requestPayload, setRequestPayload] = useState<Record<any, any>>();
|
|
33
|
+
|
|
34
|
+
const isFutureMutationsPaused = usePauseFutureRequests((state) => state.isFutureMutationsPaused);
|
|
30
35
|
|
|
31
36
|
const sendRequest = async (
|
|
32
37
|
res: (value: any) => void,
|
|
@@ -108,10 +113,23 @@ export const usePostRequest = <TResponse>({
|
|
|
108
113
|
| { requestConfig?: Partial<Omit<IMakeRequest, 'body'>> }
|
|
109
114
|
| undefined
|
|
110
115
|
) & { requestConfig?: Partial<Omit<IMakeRequest, 'body'>> }
|
|
111
|
-
): Promise<IRequestSuccess<TResponse
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
): Promise<IRequestSuccess<TResponse> | undefined> => {
|
|
117
|
+
if (!isFutureMutationsPaused) {
|
|
118
|
+
const { requestConfig, ...otherOptions } = options ?? {};
|
|
119
|
+
return mutation.mutateAsync({ data, requestConfig }, otherOptions);
|
|
120
|
+
} else {
|
|
121
|
+
setRequestPayload({ data, options });
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
114
124
|
};
|
|
115
125
|
|
|
116
|
-
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (!isFutureMutationsPaused && requestPayload) {
|
|
128
|
+
post(requestPayload.data, requestPayload.options);
|
|
129
|
+
setRequestPayload(undefined);
|
|
130
|
+
}
|
|
131
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
132
|
+
}, [isFutureMutationsPaused]);
|
|
133
|
+
|
|
134
|
+
return { post, uploadProgressPercent, ...mutation, isLoading: mutation.isLoading || isFutureMutationsPaused };
|
|
117
135
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './usePauseFutureRequests';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { create } from 'zustand';
|
|
2
|
+
|
|
3
|
+
export interface PauseFutureRequest {
|
|
4
|
+
isFutureQueriesPaused: boolean;
|
|
5
|
+
isFutureMutationsPaused: boolean;
|
|
6
|
+
|
|
7
|
+
pauseFutureMutation: (status: boolean) => void;
|
|
8
|
+
pauseFutureQueries: (status: boolean) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const usePauseFutureRequests = create<PauseFutureRequest>((set) => {
|
|
12
|
+
const pauseFutureQueries = (status: boolean) => {
|
|
13
|
+
return set({ isFutureQueriesPaused: status });
|
|
14
|
+
};
|
|
15
|
+
const pauseFutureMutation = (status: boolean) => {
|
|
16
|
+
return set({ isFutureQueriesPaused: status });
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
isFutureMutationsPaused: false,
|
|
21
|
+
isFutureQueriesPaused: false,
|
|
22
|
+
pauseFutureQueries,
|
|
23
|
+
pauseFutureMutation,
|
|
24
|
+
};
|
|
25
|
+
});
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { renderHook } from '@testing-library/react-hooks';
|
|
2
|
-
import axios from 'axios';
|
|
3
|
-
import MockAdapter from 'axios-mock-adapter';
|
|
4
|
-
import { usePostRequest } from '../../queries';
|
|
5
|
-
|
|
6
|
-
const mockAxios = new MockAdapter(axios);
|
|
7
|
-
|
|
8
|
-
describe('usePostRequest', () => {
|
|
9
|
-
const path = '/test';
|
|
10
|
-
const postData = { name: 'John Doe' };
|
|
11
|
-
const response = { id: 123, name: 'John Doe' };
|
|
12
|
-
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
mockAxios.reset();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('should return post function and mutation object', () => {
|
|
18
|
-
const { result } = renderHook(() => usePostRequest<{ id: number; name: string }>({ path }));
|
|
19
|
-
|
|
20
|
-
expect(result.current.post).toBeInstanceOf(Function);
|
|
21
|
-
expect(result.current.isLoading).toBe(false);
|
|
22
|
-
expect(result.current.isSuccess).toBe(false);
|
|
23
|
-
expect(result.current.isError).toBe(false);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should make post request and return response data', async () => {
|
|
27
|
-
mockAxios.onPost(path).reply(200, response);
|
|
28
|
-
|
|
29
|
-
const { result, waitForNextUpdate } = renderHook(() => usePostRequest<{ id: number; name: string }>({ path }));
|
|
30
|
-
|
|
31
|
-
const responsePromise = result.current.post(postData);
|
|
32
|
-
|
|
33
|
-
expect(result.current.isLoading).toBe(true);
|
|
34
|
-
|
|
35
|
-
await waitForNextUpdate();
|
|
36
|
-
|
|
37
|
-
expect(result.current.isLoading).toBe(false);
|
|
38
|
-
expect(result.current.isSuccess).toBe(true);
|
|
39
|
-
expect(result.current.data).toEqual(response);
|
|
40
|
-
expect(await responsePromise).toEqual(response);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should make post request and return error', async () => {
|
|
44
|
-
const errorMessage = 'Request failed with status code 500';
|
|
45
|
-
mockAxios.onPost(path).reply(500, { message: errorMessage });
|
|
46
|
-
|
|
47
|
-
const { result, waitForNextUpdate } = renderHook(() => usePostRequest<{ id: number; name: string }>({ path }));
|
|
48
|
-
|
|
49
|
-
const responsePromise = result.current.post(postData);
|
|
50
|
-
|
|
51
|
-
expect(result.current.isLoading).toBe(true);
|
|
52
|
-
|
|
53
|
-
await waitForNextUpdate();
|
|
54
|
-
|
|
55
|
-
expect(result.current.isLoading).toBe(false);
|
|
56
|
-
expect(result.current.isError).toBe(true);
|
|
57
|
-
expect(result.current.error?.message).toBe(errorMessage);
|
|
58
|
-
|
|
59
|
-
await expect(responsePromise).rejects.toEqual({
|
|
60
|
-
message: errorMessage,
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should make post request with FormData', async () => {
|
|
65
|
-
const formData = new FormData();
|
|
66
|
-
formData.append('name', 'John Doe');
|
|
67
|
-
mockAxios.onPost(path).reply(200, response);
|
|
68
|
-
|
|
69
|
-
const { result } = renderHook(() => usePostRequest<{ id: number; name: string }>({ path, isFormData: true }));
|
|
70
|
-
|
|
71
|
-
const responsePromise = result.current.post(formData);
|
|
72
|
-
|
|
73
|
-
expect(result.current.isLoading).toBe(true);
|
|
74
|
-
|
|
75
|
-
await expect(responsePromise).resolves.toEqual(response);
|
|
76
|
-
});
|
|
77
|
-
});
|