@@ -28,6 +28,13 @@ export interface UseQueryOptions<QueryData, Data> {
28
28
enabled ?: boolean ;
29
29
}
30
30
31
+ interface UseQueryCallbackParams {
32
+ /* The abort signal */
33
+ signal : AbortSignal ;
34
+ /* The depends for the hook */
35
+ keys : DependencyList ;
36
+ }
37
+
31
38
/* The use query return type */
32
39
export interface UseQueryReturn < Data > {
33
40
/* The state of the query */
@@ -44,6 +51,10 @@ export interface UseQueryReturn<Data> {
44
51
refetch : ( ) => void ;
45
52
/* The refetching state of the query */
46
53
isRefetching : boolean ;
54
+ /* The abort function */
55
+ abort : AbortController [ 'abort' ] ;
56
+ /* The aborted state of the query */
57
+ isAborted : boolean ;
47
58
}
48
59
49
60
/**
@@ -67,7 +78,7 @@ export interface UseQueryReturn<Data> {
67
78
* const { data, isLoading, isError, isSuccess, error, refetch, isRefetching } = useQuery(() => fetch('url'));
68
79
*/
69
80
export const useQuery = < QueryData , Data = QueryData > (
70
- callback : ( ) => Promise < QueryData > ,
81
+ callback : ( params : UseQueryCallbackParams ) => Promise < QueryData > ,
71
82
options ?: UseQueryOptions < QueryData , Data >
72
83
) : UseQueryReturn < Data > => {
73
84
const enabled = options ?. enabled ?? true ;
@@ -77,16 +88,28 @@ export const useQuery = <QueryData, Data = QueryData>(
77
88
const [ isError , setIsError ] = useState ( false ) ;
78
89
const [ isRefetching , setIsRefetching ] = useState ( false ) ;
79
90
const [ isSuccess , setIsSuccess ] = useState ( ! ! options ?. initialData ) ;
91
+ const [ isAborted , setIsAborted ] = useState ( ! ! options ?. initialData ) ;
80
92
81
93
const [ error , setError ] = useState < Error | undefined > ( undefined ) ;
82
94
const [ data , setData ] = useState < Data | undefined > ( options ?. initialData ) ;
83
95
96
+ const abortControllerRef = useRef < AbortController > ( new AbortController ( ) ) ;
84
97
const intervalIdRef = useRef < ReturnType < typeof setInterval > > ( ) ;
85
98
99
+ const keys = options ?. keys ?? [ ] ;
100
+
101
+ const abort = ( ) => {
102
+ abortControllerRef . current . abort ( ) ;
103
+ abortControllerRef . current = new AbortController ( ) ;
104
+ abortControllerRef . current . signal . onabort = ( ) => setIsAborted ( true ) ;
105
+ } ;
106
+
86
107
const request = ( action : 'init' | 'refetch' ) => {
108
+ abort ( ) ;
87
109
setIsLoading ( true ) ;
110
+
88
111
if ( action === 'refetch' ) setIsRefetching ( true ) ;
89
- callback ( )
112
+ callback ( { signal : abortControllerRef . current . signal , keys } )
90
113
. then ( ( response ) => {
91
114
const data = options ?. select ? options ?. select ( response ) : response ;
92
115
options ?. onSuccess ?.( data as Data ) ;
@@ -130,13 +153,13 @@ export const useQuery = <QueryData, Data = QueryData>(
130
153
useDidUpdate ( ( ) => {
131
154
if ( ! enabled ) return ;
132
155
request ( 'refetch' ) ;
133
- } , [ enabled , ...( options ?. keys ?? [ ] ) ] ) ;
156
+ } , [ enabled , ...keys ] ) ;
134
157
135
158
useEffect ( ( ) => {
136
159
return ( ) => {
137
160
clearInterval ( intervalIdRef . current ) ;
138
161
} ;
139
- } , [ enabled , options ?. refetchInterval , options ?. retry , ...( options ?. keys ?? [ ] ) ] ) ;
162
+ } , [ enabled , options ?. refetchInterval , options ?. retry , ...keys ] ) ;
140
163
141
164
const refetch = ( ) => request ( 'refetch' ) ;
142
165
@@ -146,12 +169,14 @@ export const useQuery = <QueryData, Data = QueryData>(
146
169
: options ?. placeholderData ;
147
170
148
171
return {
172
+ abort,
149
173
data : data ?? placeholderData ,
150
174
error,
151
175
refetch,
152
176
isLoading,
153
177
isError,
154
178
isSuccess,
155
- isRefetching
179
+ isRefetching,
180
+ isAborted
156
181
} ;
157
182
} ;
0 commit comments