@tanstack/react-query 4.0.5
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/build/cjs/query-core/build/esm/index.js +3110 -0
- package/build/cjs/query-core/build/esm/index.js.map +1 -0
- package/build/cjs/react-query/src/Hydrate.js +66 -0
- package/build/cjs/react-query/src/Hydrate.js.map +1 -0
- package/build/cjs/react-query/src/QueryClientProvider.js +96 -0
- package/build/cjs/react-query/src/QueryClientProvider.js.map +1 -0
- package/build/cjs/react-query/src/QueryErrorResetBoundary.js +67 -0
- package/build/cjs/react-query/src/QueryErrorResetBoundary.js.map +1 -0
- package/build/cjs/react-query/src/index.js +64 -0
- package/build/cjs/react-query/src/index.js.map +1 -0
- package/build/cjs/react-query/src/isRestoring.js +43 -0
- package/build/cjs/react-query/src/isRestoring.js.map +1 -0
- package/build/cjs/react-query/src/useBaseQuery.js +117 -0
- package/build/cjs/react-query/src/useBaseQuery.js.map +1 -0
- package/build/cjs/react-query/src/useInfiniteQuery.js +24 -0
- package/build/cjs/react-query/src/useInfiniteQuery.js.map +1 -0
- package/build/cjs/react-query/src/useIsFetching.js +50 -0
- package/build/cjs/react-query/src/useIsFetching.js.map +1 -0
- package/build/cjs/react-query/src/useIsMutating.js +50 -0
- package/build/cjs/react-query/src/useIsMutating.js.map +1 -0
- package/build/cjs/react-query/src/useMutation.js +68 -0
- package/build/cjs/react-query/src/useMutation.js.map +1 -0
- package/build/cjs/react-query/src/useQueries.js +71 -0
- package/build/cjs/react-query/src/useQueries.js.map +1 -0
- package/build/cjs/react-query/src/useQuery.js +24 -0
- package/build/cjs/react-query/src/useQuery.js.map +1 -0
- package/build/cjs/react-query/src/utils.js +25 -0
- package/build/cjs/react-query/src/utils.js.map +1 -0
- package/build/esm/index.js +3368 -0
- package/build/esm/index.js.map +1 -0
- package/build/stats-html.html +2689 -0
- package/build/stats.json +666 -0
- package/build/types/packages/query-core/src/focusManager.d.ts +16 -0
- package/build/types/packages/query-core/src/hydration.d.ts +34 -0
- package/build/types/packages/query-core/src/index.d.ts +20 -0
- package/build/types/packages/query-core/src/infiniteQueryBehavior.d.ts +15 -0
- package/build/types/packages/query-core/src/infiniteQueryObserver.d.ts +18 -0
- package/build/types/packages/query-core/src/logger.d.ts +8 -0
- package/build/types/packages/query-core/src/mutation.d.ts +70 -0
- package/build/types/packages/query-core/src/mutationCache.d.ts +52 -0
- package/build/types/packages/query-core/src/mutationObserver.d.ts +23 -0
- package/build/types/packages/query-core/src/notifyManager.d.ts +18 -0
- package/build/types/packages/query-core/src/onlineManager.d.ts +16 -0
- package/build/types/packages/query-core/src/queriesObserver.d.ts +23 -0
- package/build/types/packages/query-core/src/query.d.ts +119 -0
- package/build/types/packages/query-core/src/queryCache.d.ts +59 -0
- package/build/types/packages/query-core/src/queryClient.d.ts +65 -0
- package/build/types/packages/query-core/src/queryObserver.d.ts +61 -0
- package/build/types/packages/query-core/src/removable.d.ts +9 -0
- package/build/types/packages/query-core/src/retryer.d.ts +33 -0
- package/build/types/packages/query-core/src/subscribable.d.ts +10 -0
- package/build/types/packages/query-core/src/types.d.ts +417 -0
- package/build/types/packages/query-core/src/utils.d.ts +99 -0
- package/build/types/packages/react-query/src/Hydrate.d.ts +10 -0
- package/build/types/packages/react-query/src/QueryClientProvider.d.ts +24 -0
- package/build/types/packages/react-query/src/QueryErrorResetBoundary.d.ts +12 -0
- package/build/types/packages/react-query/src/__tests__/Hydrate.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/QueryClientProvider.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/QueryResetErrorBoundary.test.d.ts +6 -0
- package/build/types/packages/react-query/src/__tests__/ssr-hydration.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/ssr.test.d.ts +4 -0
- package/build/types/packages/react-query/src/__tests__/suspense.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useInfiniteQuery.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useIsFetching.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useIsMutating.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useMutation.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useQueries.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useQuery.test.d.ts +1 -0
- package/build/types/packages/react-query/src/__tests__/useQuery.types.test.d.ts +2 -0
- package/build/types/packages/react-query/src/__tests__/utils.d.ts +8 -0
- package/build/types/packages/react-query/src/index.d.ts +17 -0
- package/build/types/packages/react-query/src/isRestoring.d.ts +3 -0
- package/build/types/packages/react-query/src/reactBatchedUpdates.d.ts +2 -0
- package/build/types/packages/react-query/src/reactBatchedUpdates.native.d.ts +2 -0
- package/build/types/packages/react-query/src/setBatchUpdatesFn.d.ts +1 -0
- package/build/types/packages/react-query/src/types.d.ts +35 -0
- package/build/types/packages/react-query/src/useBaseQuery.d.ts +3 -0
- package/build/types/packages/react-query/src/useInfiniteQuery.d.ts +5 -0
- package/build/types/packages/react-query/src/useIsFetching.d.ts +7 -0
- package/build/types/packages/react-query/src/useIsMutating.d.ts +7 -0
- package/build/types/packages/react-query/src/useMutation.d.ts +6 -0
- package/build/types/packages/react-query/src/useQueries.d.ts +49 -0
- package/build/types/packages/react-query/src/useQuery.d.ts +20 -0
- package/build/types/packages/react-query/src/utils.d.ts +1 -0
- package/build/types/tests/utils.d.ts +24 -0
- package/build/umd/index.development.js +3429 -0
- package/build/umd/index.development.js.map +1 -0
- package/build/umd/index.production.js +22 -0
- package/build/umd/index.production.js.map +1 -0
- package/codemods/v4/key-transformation.js +138 -0
- package/codemods/v4/replace-import-specifier.js +25 -0
- package/codemods/v4/utils/index.js +166 -0
- package/codemods/v4/utils/replacers/key-replacer.js +160 -0
- package/codemods/v4/utils/transformers/query-cache-transformer.js +115 -0
- package/codemods/v4/utils/transformers/query-client-transformer.js +49 -0
- package/codemods/v4/utils/transformers/use-query-like-transformer.js +32 -0
- package/codemods/v4/utils/unprocessable-key-error.js +8 -0
- package/package.json +63 -0
- package/src/Hydrate.tsx +36 -0
- package/src/QueryClientProvider.tsx +90 -0
- package/src/QueryErrorResetBoundary.tsx +52 -0
- package/src/__tests__/Hydrate.test.tsx +247 -0
- package/src/__tests__/QueryClientProvider.test.tsx +275 -0
- package/src/__tests__/QueryResetErrorBoundary.test.tsx +630 -0
- package/src/__tests__/ssr-hydration.test.tsx +274 -0
- package/src/__tests__/ssr.test.tsx +151 -0
- package/src/__tests__/suspense.test.tsx +1015 -0
- package/src/__tests__/useInfiniteQuery.test.tsx +1773 -0
- package/src/__tests__/useIsFetching.test.tsx +274 -0
- package/src/__tests__/useIsMutating.test.tsx +260 -0
- package/src/__tests__/useMutation.test.tsx +1099 -0
- package/src/__tests__/useQueries.test.tsx +1107 -0
- package/src/__tests__/useQuery.test.tsx +5746 -0
- package/src/__tests__/useQuery.types.test.tsx +157 -0
- package/src/__tests__/utils.tsx +45 -0
- package/src/index.ts +29 -0
- package/src/isRestoring.tsx +6 -0
- package/src/reactBatchedUpdates.native.ts +4 -0
- package/src/reactBatchedUpdates.ts +2 -0
- package/src/setBatchUpdatesFn.ts +4 -0
- package/src/types.ts +122 -0
- package/src/useBaseQuery.ts +140 -0
- package/src/useInfiniteQuery.ts +101 -0
- package/src/useIsFetching.ts +39 -0
- package/src/useIsMutating.ts +43 -0
- package/src/useMutation.ts +126 -0
- package/src/useQueries.ts +192 -0
- package/src/useQuery.ts +104 -0
- package/src/utils.ts +11 -0
|
@@ -0,0 +1,630 @@
|
|
|
1
|
+
import { waitFor, fireEvent } from '@testing-library/react'
|
|
2
|
+
import { ErrorBoundary } from 'react-error-boundary'
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
|
|
5
|
+
import { sleep, queryKey, createQueryClient } from '../../../../tests/utils'
|
|
6
|
+
import { renderWithClient } from './utils'
|
|
7
|
+
import { useQuery, QueryCache, QueryErrorResetBoundary } from '..'
|
|
8
|
+
|
|
9
|
+
// TODO: This should be removed with the types for react-error-boundary get updated.
|
|
10
|
+
declare module 'react-error-boundary' {
|
|
11
|
+
interface ErrorBoundaryPropsWithFallback {
|
|
12
|
+
children: any
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe('QueryErrorResetBoundary', () => {
|
|
17
|
+
const queryCache = new QueryCache()
|
|
18
|
+
const queryClient = createQueryClient({ queryCache })
|
|
19
|
+
|
|
20
|
+
it('should retry fetch if the reset error boundary has been reset', async () => {
|
|
21
|
+
const key = queryKey()
|
|
22
|
+
|
|
23
|
+
let succeed = false
|
|
24
|
+
|
|
25
|
+
function Page() {
|
|
26
|
+
const { data } = useQuery(
|
|
27
|
+
key,
|
|
28
|
+
async () => {
|
|
29
|
+
await sleep(10)
|
|
30
|
+
if (!succeed) {
|
|
31
|
+
throw new Error('Error')
|
|
32
|
+
} else {
|
|
33
|
+
return 'data'
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
retry: false,
|
|
38
|
+
useErrorBoundary: true,
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
return <div>{data}</div>
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const rendered = renderWithClient(
|
|
45
|
+
queryClient,
|
|
46
|
+
<QueryErrorResetBoundary>
|
|
47
|
+
{({ reset }) => (
|
|
48
|
+
<ErrorBoundary
|
|
49
|
+
onReset={reset}
|
|
50
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
51
|
+
<div>
|
|
52
|
+
<div>error boundary</div>
|
|
53
|
+
<button
|
|
54
|
+
onClick={() => {
|
|
55
|
+
resetErrorBoundary()
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
58
|
+
retry
|
|
59
|
+
</button>
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
>
|
|
63
|
+
<Page />
|
|
64
|
+
</ErrorBoundary>
|
|
65
|
+
)}
|
|
66
|
+
</QueryErrorResetBoundary>,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
70
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
71
|
+
succeed = true
|
|
72
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
73
|
+
await waitFor(() => rendered.getByText('data'))
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('should not throw error if query is disabled', async () => {
|
|
77
|
+
const key = queryKey()
|
|
78
|
+
|
|
79
|
+
let succeed = false
|
|
80
|
+
|
|
81
|
+
function Page() {
|
|
82
|
+
const { data, status } = useQuery(
|
|
83
|
+
key,
|
|
84
|
+
async () => {
|
|
85
|
+
await sleep(10)
|
|
86
|
+
if (!succeed) {
|
|
87
|
+
throw new Error('Error')
|
|
88
|
+
} else {
|
|
89
|
+
return 'data'
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
retry: false,
|
|
94
|
+
enabled: !succeed,
|
|
95
|
+
useErrorBoundary: true,
|
|
96
|
+
},
|
|
97
|
+
)
|
|
98
|
+
return (
|
|
99
|
+
<div>
|
|
100
|
+
<div>status: {status}</div>
|
|
101
|
+
<div>{data}</div>
|
|
102
|
+
</div>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const rendered = renderWithClient(
|
|
107
|
+
queryClient,
|
|
108
|
+
<QueryErrorResetBoundary>
|
|
109
|
+
{({ reset }) => (
|
|
110
|
+
<ErrorBoundary
|
|
111
|
+
onReset={reset}
|
|
112
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
113
|
+
<div>
|
|
114
|
+
<div>error boundary</div>
|
|
115
|
+
<button
|
|
116
|
+
onClick={() => {
|
|
117
|
+
resetErrorBoundary()
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
retry
|
|
121
|
+
</button>
|
|
122
|
+
</div>
|
|
123
|
+
)}
|
|
124
|
+
>
|
|
125
|
+
<Page />
|
|
126
|
+
</ErrorBoundary>
|
|
127
|
+
)}
|
|
128
|
+
</QueryErrorResetBoundary>,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
132
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
133
|
+
succeed = true
|
|
134
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
135
|
+
await waitFor(() => rendered.getByText('status: error'))
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it('should not throw error if query is disabled, and refetch if query becomes enabled again', async () => {
|
|
139
|
+
const key = queryKey()
|
|
140
|
+
|
|
141
|
+
let succeed = false
|
|
142
|
+
|
|
143
|
+
function Page() {
|
|
144
|
+
const [enabled, setEnabled] = React.useState(false)
|
|
145
|
+
const { data } = useQuery(
|
|
146
|
+
key,
|
|
147
|
+
async () => {
|
|
148
|
+
await sleep(10)
|
|
149
|
+
if (!succeed) {
|
|
150
|
+
throw new Error('Error')
|
|
151
|
+
} else {
|
|
152
|
+
return 'data'
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
retry: false,
|
|
157
|
+
enabled,
|
|
158
|
+
useErrorBoundary: true,
|
|
159
|
+
},
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
React.useEffect(() => {
|
|
163
|
+
setEnabled(true)
|
|
164
|
+
}, [])
|
|
165
|
+
|
|
166
|
+
return <div>{data}</div>
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const rendered = renderWithClient(
|
|
170
|
+
queryClient,
|
|
171
|
+
<QueryErrorResetBoundary>
|
|
172
|
+
{({ reset }) => (
|
|
173
|
+
<ErrorBoundary
|
|
174
|
+
onReset={reset}
|
|
175
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
176
|
+
<div>
|
|
177
|
+
<div>error boundary</div>
|
|
178
|
+
<button
|
|
179
|
+
onClick={() => {
|
|
180
|
+
resetErrorBoundary()
|
|
181
|
+
}}
|
|
182
|
+
>
|
|
183
|
+
retry
|
|
184
|
+
</button>
|
|
185
|
+
</div>
|
|
186
|
+
)}
|
|
187
|
+
>
|
|
188
|
+
<Page />
|
|
189
|
+
</ErrorBoundary>
|
|
190
|
+
)}
|
|
191
|
+
</QueryErrorResetBoundary>,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
195
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
196
|
+
succeed = true
|
|
197
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
198
|
+
await waitFor(() => rendered.getByText('data'))
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
it('should throw error if query is disabled and manually refetched', async () => {
|
|
202
|
+
const key = queryKey()
|
|
203
|
+
|
|
204
|
+
function Page() {
|
|
205
|
+
const { data, refetch, status, fetchStatus } = useQuery<string>(
|
|
206
|
+
key,
|
|
207
|
+
async () => {
|
|
208
|
+
throw new Error('Error')
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
retry: false,
|
|
212
|
+
enabled: false,
|
|
213
|
+
useErrorBoundary: true,
|
|
214
|
+
},
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<div>
|
|
219
|
+
<button onClick={() => refetch()}>refetch</button>
|
|
220
|
+
<div>
|
|
221
|
+
status: {status}, fetchStatus: {fetchStatus}
|
|
222
|
+
</div>
|
|
223
|
+
<div>{data}</div>
|
|
224
|
+
</div>
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const rendered = renderWithClient(
|
|
229
|
+
queryClient,
|
|
230
|
+
<QueryErrorResetBoundary>
|
|
231
|
+
{({ reset }) => (
|
|
232
|
+
<ErrorBoundary
|
|
233
|
+
onReset={reset}
|
|
234
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
235
|
+
<div>
|
|
236
|
+
<div>error boundary</div>
|
|
237
|
+
<button
|
|
238
|
+
onClick={() => {
|
|
239
|
+
resetErrorBoundary()
|
|
240
|
+
}}
|
|
241
|
+
>
|
|
242
|
+
retry
|
|
243
|
+
</button>
|
|
244
|
+
</div>
|
|
245
|
+
)}
|
|
246
|
+
>
|
|
247
|
+
<Page />
|
|
248
|
+
</ErrorBoundary>
|
|
249
|
+
)}
|
|
250
|
+
</QueryErrorResetBoundary>,
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
await waitFor(() =>
|
|
254
|
+
rendered.getByText('status: loading, fetchStatus: idle'),
|
|
255
|
+
)
|
|
256
|
+
fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))
|
|
257
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
258
|
+
})
|
|
259
|
+
|
|
260
|
+
it('should not retry fetch if the reset error boundary has not been reset', async () => {
|
|
261
|
+
const key = queryKey()
|
|
262
|
+
|
|
263
|
+
let succeed = false
|
|
264
|
+
|
|
265
|
+
function Page() {
|
|
266
|
+
const { data } = useQuery(
|
|
267
|
+
key,
|
|
268
|
+
async () => {
|
|
269
|
+
await sleep(10)
|
|
270
|
+
if (!succeed) {
|
|
271
|
+
throw new Error('Error')
|
|
272
|
+
} else {
|
|
273
|
+
return 'data'
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
retry: false,
|
|
278
|
+
useErrorBoundary: true,
|
|
279
|
+
},
|
|
280
|
+
)
|
|
281
|
+
return <div>{data}</div>
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const rendered = renderWithClient(
|
|
285
|
+
queryClient,
|
|
286
|
+
<QueryErrorResetBoundary>
|
|
287
|
+
{() => (
|
|
288
|
+
<ErrorBoundary
|
|
289
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
290
|
+
<div>
|
|
291
|
+
<div>error boundary</div>
|
|
292
|
+
<button
|
|
293
|
+
onClick={() => {
|
|
294
|
+
resetErrorBoundary()
|
|
295
|
+
}}
|
|
296
|
+
>
|
|
297
|
+
retry
|
|
298
|
+
</button>
|
|
299
|
+
</div>
|
|
300
|
+
)}
|
|
301
|
+
>
|
|
302
|
+
<Page />
|
|
303
|
+
</ErrorBoundary>
|
|
304
|
+
)}
|
|
305
|
+
</QueryErrorResetBoundary>,
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
309
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
310
|
+
succeed = true
|
|
311
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
312
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
it('should retry fetch if the reset error boundary has been reset and the query contains data from a previous fetch', async () => {
|
|
316
|
+
const key = queryKey()
|
|
317
|
+
|
|
318
|
+
let succeed = false
|
|
319
|
+
|
|
320
|
+
function Page() {
|
|
321
|
+
const { data } = useQuery(
|
|
322
|
+
key,
|
|
323
|
+
async () => {
|
|
324
|
+
await sleep(10)
|
|
325
|
+
if (!succeed) {
|
|
326
|
+
throw new Error('Error')
|
|
327
|
+
} else {
|
|
328
|
+
return 'data'
|
|
329
|
+
}
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
retry: false,
|
|
333
|
+
useErrorBoundary: true,
|
|
334
|
+
initialData: 'initial',
|
|
335
|
+
},
|
|
336
|
+
)
|
|
337
|
+
return <div>{data}</div>
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const rendered = renderWithClient(
|
|
341
|
+
queryClient,
|
|
342
|
+
<QueryErrorResetBoundary>
|
|
343
|
+
{({ reset }) => (
|
|
344
|
+
<ErrorBoundary
|
|
345
|
+
onReset={reset}
|
|
346
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
347
|
+
<div>
|
|
348
|
+
<div>error boundary</div>
|
|
349
|
+
<button
|
|
350
|
+
onClick={() => {
|
|
351
|
+
resetErrorBoundary()
|
|
352
|
+
}}
|
|
353
|
+
>
|
|
354
|
+
retry
|
|
355
|
+
</button>
|
|
356
|
+
</div>
|
|
357
|
+
)}
|
|
358
|
+
>
|
|
359
|
+
<Page />
|
|
360
|
+
</ErrorBoundary>
|
|
361
|
+
)}
|
|
362
|
+
</QueryErrorResetBoundary>,
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
366
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
367
|
+
succeed = true
|
|
368
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
369
|
+
await waitFor(() => rendered.getByText('data'))
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
it('should not retry fetch if the reset error boundary has not been reset after a previous reset', async () => {
|
|
373
|
+
const key = queryKey()
|
|
374
|
+
|
|
375
|
+
let succeed = false
|
|
376
|
+
let shouldReset = true
|
|
377
|
+
|
|
378
|
+
function Page() {
|
|
379
|
+
const { data } = useQuery(
|
|
380
|
+
key,
|
|
381
|
+
async () => {
|
|
382
|
+
await sleep(10)
|
|
383
|
+
if (!succeed) {
|
|
384
|
+
throw new Error('Error')
|
|
385
|
+
} else {
|
|
386
|
+
return 'data'
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
retry: false,
|
|
391
|
+
useErrorBoundary: true,
|
|
392
|
+
},
|
|
393
|
+
)
|
|
394
|
+
return <div>{data}</div>
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const rendered = renderWithClient(
|
|
398
|
+
queryClient,
|
|
399
|
+
<QueryErrorResetBoundary>
|
|
400
|
+
{({ reset }) => (
|
|
401
|
+
<ErrorBoundary
|
|
402
|
+
onReset={() => {
|
|
403
|
+
if (shouldReset) {
|
|
404
|
+
reset()
|
|
405
|
+
}
|
|
406
|
+
}}
|
|
407
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
408
|
+
<div>
|
|
409
|
+
<div>error boundary</div>
|
|
410
|
+
<button
|
|
411
|
+
onClick={() => {
|
|
412
|
+
resetErrorBoundary()
|
|
413
|
+
}}
|
|
414
|
+
>
|
|
415
|
+
retry
|
|
416
|
+
</button>
|
|
417
|
+
</div>
|
|
418
|
+
)}
|
|
419
|
+
>
|
|
420
|
+
<Page />
|
|
421
|
+
</ErrorBoundary>
|
|
422
|
+
)}
|
|
423
|
+
</QueryErrorResetBoundary>,
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
427
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
428
|
+
shouldReset = true
|
|
429
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
430
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
431
|
+
succeed = true
|
|
432
|
+
shouldReset = false
|
|
433
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
434
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
435
|
+
})
|
|
436
|
+
|
|
437
|
+
it('should throw again on error after the reset error boundary has been reset', async () => {
|
|
438
|
+
const key = queryKey()
|
|
439
|
+
let fetchCount = 0
|
|
440
|
+
|
|
441
|
+
function Page() {
|
|
442
|
+
const { data } = useQuery<string>(
|
|
443
|
+
key,
|
|
444
|
+
async () => {
|
|
445
|
+
fetchCount++
|
|
446
|
+
await sleep(10)
|
|
447
|
+
throw new Error('Error')
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
retry: false,
|
|
451
|
+
useErrorBoundary: true,
|
|
452
|
+
},
|
|
453
|
+
)
|
|
454
|
+
return <div>{data}</div>
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const rendered = renderWithClient(
|
|
458
|
+
queryClient,
|
|
459
|
+
<QueryErrorResetBoundary>
|
|
460
|
+
{({ reset }) => (
|
|
461
|
+
<ErrorBoundary
|
|
462
|
+
onReset={reset}
|
|
463
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
464
|
+
<div>
|
|
465
|
+
<div>error boundary</div>
|
|
466
|
+
<button
|
|
467
|
+
onClick={() => {
|
|
468
|
+
resetErrorBoundary()
|
|
469
|
+
}}
|
|
470
|
+
>
|
|
471
|
+
retry
|
|
472
|
+
</button>
|
|
473
|
+
</div>
|
|
474
|
+
)}
|
|
475
|
+
>
|
|
476
|
+
<Page />
|
|
477
|
+
</ErrorBoundary>
|
|
478
|
+
)}
|
|
479
|
+
</QueryErrorResetBoundary>,
|
|
480
|
+
)
|
|
481
|
+
|
|
482
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
483
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
484
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
485
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
486
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
487
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
488
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
489
|
+
expect(fetchCount).toBe(3)
|
|
490
|
+
})
|
|
491
|
+
|
|
492
|
+
it('should never render the component while the query is in error state', async () => {
|
|
493
|
+
const key = queryKey()
|
|
494
|
+
let fetchCount = 0
|
|
495
|
+
let renders = 0
|
|
496
|
+
|
|
497
|
+
function Page() {
|
|
498
|
+
const { data } = useQuery(
|
|
499
|
+
key,
|
|
500
|
+
async () => {
|
|
501
|
+
fetchCount++
|
|
502
|
+
await sleep(10)
|
|
503
|
+
if (fetchCount > 2) {
|
|
504
|
+
return 'data'
|
|
505
|
+
} else {
|
|
506
|
+
throw new Error('Error')
|
|
507
|
+
}
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
retry: false,
|
|
511
|
+
suspense: true,
|
|
512
|
+
},
|
|
513
|
+
)
|
|
514
|
+
renders++
|
|
515
|
+
return <div>{data}</div>
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
const rendered = renderWithClient(
|
|
519
|
+
queryClient,
|
|
520
|
+
<QueryErrorResetBoundary>
|
|
521
|
+
{({ reset }) => (
|
|
522
|
+
<ErrorBoundary
|
|
523
|
+
onReset={reset}
|
|
524
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
525
|
+
<div>
|
|
526
|
+
<div>error boundary</div>
|
|
527
|
+
<button
|
|
528
|
+
onClick={() => {
|
|
529
|
+
resetErrorBoundary()
|
|
530
|
+
}}
|
|
531
|
+
>
|
|
532
|
+
retry
|
|
533
|
+
</button>
|
|
534
|
+
</div>
|
|
535
|
+
)}
|
|
536
|
+
>
|
|
537
|
+
<React.Suspense fallback={<div>loading</div>}>
|
|
538
|
+
<Page />
|
|
539
|
+
</React.Suspense>
|
|
540
|
+
</ErrorBoundary>
|
|
541
|
+
)}
|
|
542
|
+
</QueryErrorResetBoundary>,
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
546
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
547
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
548
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
549
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
550
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
551
|
+
await waitFor(() => rendered.getByText('data'))
|
|
552
|
+
expect(fetchCount).toBe(3)
|
|
553
|
+
expect(renders).toBe(1)
|
|
554
|
+
})
|
|
555
|
+
|
|
556
|
+
it('should render children', async () => {
|
|
557
|
+
function Page() {
|
|
558
|
+
return (
|
|
559
|
+
<div>
|
|
560
|
+
<span>page</span>
|
|
561
|
+
</div>
|
|
562
|
+
)
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const rendered = renderWithClient(
|
|
566
|
+
queryClient,
|
|
567
|
+
<QueryErrorResetBoundary>
|
|
568
|
+
<Page />
|
|
569
|
+
</QueryErrorResetBoundary>,
|
|
570
|
+
)
|
|
571
|
+
|
|
572
|
+
expect(rendered.queryByText('page')).not.toBeNull()
|
|
573
|
+
})
|
|
574
|
+
|
|
575
|
+
it('should show error boundary when using tracked queries even though we do not track the error field', async () => {
|
|
576
|
+
const key = queryKey()
|
|
577
|
+
|
|
578
|
+
let succeed = false
|
|
579
|
+
|
|
580
|
+
function Page() {
|
|
581
|
+
const { data } = useQuery(
|
|
582
|
+
key,
|
|
583
|
+
async () => {
|
|
584
|
+
await sleep(10)
|
|
585
|
+
if (!succeed) {
|
|
586
|
+
throw new Error('Error')
|
|
587
|
+
} else {
|
|
588
|
+
return 'data'
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
retry: false,
|
|
593
|
+
useErrorBoundary: true,
|
|
594
|
+
},
|
|
595
|
+
)
|
|
596
|
+
return <div>{data}</div>
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
const rendered = renderWithClient(
|
|
600
|
+
queryClient,
|
|
601
|
+
<QueryErrorResetBoundary>
|
|
602
|
+
{({ reset }) => (
|
|
603
|
+
<ErrorBoundary
|
|
604
|
+
onReset={reset}
|
|
605
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
606
|
+
<div>
|
|
607
|
+
<div>error boundary</div>
|
|
608
|
+
<button
|
|
609
|
+
onClick={() => {
|
|
610
|
+
resetErrorBoundary()
|
|
611
|
+
}}
|
|
612
|
+
>
|
|
613
|
+
retry
|
|
614
|
+
</button>
|
|
615
|
+
</div>
|
|
616
|
+
)}
|
|
617
|
+
>
|
|
618
|
+
<Page />
|
|
619
|
+
</ErrorBoundary>
|
|
620
|
+
)}
|
|
621
|
+
</QueryErrorResetBoundary>,
|
|
622
|
+
)
|
|
623
|
+
|
|
624
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
625
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
626
|
+
succeed = true
|
|
627
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
628
|
+
await waitFor(() => rendered.getByText('data'))
|
|
629
|
+
})
|
|
630
|
+
})
|