@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.
Files changed (129) hide show
  1. package/build/cjs/query-core/build/esm/index.js +3110 -0
  2. package/build/cjs/query-core/build/esm/index.js.map +1 -0
  3. package/build/cjs/react-query/src/Hydrate.js +66 -0
  4. package/build/cjs/react-query/src/Hydrate.js.map +1 -0
  5. package/build/cjs/react-query/src/QueryClientProvider.js +96 -0
  6. package/build/cjs/react-query/src/QueryClientProvider.js.map +1 -0
  7. package/build/cjs/react-query/src/QueryErrorResetBoundary.js +67 -0
  8. package/build/cjs/react-query/src/QueryErrorResetBoundary.js.map +1 -0
  9. package/build/cjs/react-query/src/index.js +64 -0
  10. package/build/cjs/react-query/src/index.js.map +1 -0
  11. package/build/cjs/react-query/src/isRestoring.js +43 -0
  12. package/build/cjs/react-query/src/isRestoring.js.map +1 -0
  13. package/build/cjs/react-query/src/useBaseQuery.js +117 -0
  14. package/build/cjs/react-query/src/useBaseQuery.js.map +1 -0
  15. package/build/cjs/react-query/src/useInfiniteQuery.js +24 -0
  16. package/build/cjs/react-query/src/useInfiniteQuery.js.map +1 -0
  17. package/build/cjs/react-query/src/useIsFetching.js +50 -0
  18. package/build/cjs/react-query/src/useIsFetching.js.map +1 -0
  19. package/build/cjs/react-query/src/useIsMutating.js +50 -0
  20. package/build/cjs/react-query/src/useIsMutating.js.map +1 -0
  21. package/build/cjs/react-query/src/useMutation.js +68 -0
  22. package/build/cjs/react-query/src/useMutation.js.map +1 -0
  23. package/build/cjs/react-query/src/useQueries.js +71 -0
  24. package/build/cjs/react-query/src/useQueries.js.map +1 -0
  25. package/build/cjs/react-query/src/useQuery.js +24 -0
  26. package/build/cjs/react-query/src/useQuery.js.map +1 -0
  27. package/build/cjs/react-query/src/utils.js +25 -0
  28. package/build/cjs/react-query/src/utils.js.map +1 -0
  29. package/build/esm/index.js +3368 -0
  30. package/build/esm/index.js.map +1 -0
  31. package/build/stats-html.html +2689 -0
  32. package/build/stats.json +666 -0
  33. package/build/types/packages/query-core/src/focusManager.d.ts +16 -0
  34. package/build/types/packages/query-core/src/hydration.d.ts +34 -0
  35. package/build/types/packages/query-core/src/index.d.ts +20 -0
  36. package/build/types/packages/query-core/src/infiniteQueryBehavior.d.ts +15 -0
  37. package/build/types/packages/query-core/src/infiniteQueryObserver.d.ts +18 -0
  38. package/build/types/packages/query-core/src/logger.d.ts +8 -0
  39. package/build/types/packages/query-core/src/mutation.d.ts +70 -0
  40. package/build/types/packages/query-core/src/mutationCache.d.ts +52 -0
  41. package/build/types/packages/query-core/src/mutationObserver.d.ts +23 -0
  42. package/build/types/packages/query-core/src/notifyManager.d.ts +18 -0
  43. package/build/types/packages/query-core/src/onlineManager.d.ts +16 -0
  44. package/build/types/packages/query-core/src/queriesObserver.d.ts +23 -0
  45. package/build/types/packages/query-core/src/query.d.ts +119 -0
  46. package/build/types/packages/query-core/src/queryCache.d.ts +59 -0
  47. package/build/types/packages/query-core/src/queryClient.d.ts +65 -0
  48. package/build/types/packages/query-core/src/queryObserver.d.ts +61 -0
  49. package/build/types/packages/query-core/src/removable.d.ts +9 -0
  50. package/build/types/packages/query-core/src/retryer.d.ts +33 -0
  51. package/build/types/packages/query-core/src/subscribable.d.ts +10 -0
  52. package/build/types/packages/query-core/src/types.d.ts +417 -0
  53. package/build/types/packages/query-core/src/utils.d.ts +99 -0
  54. package/build/types/packages/react-query/src/Hydrate.d.ts +10 -0
  55. package/build/types/packages/react-query/src/QueryClientProvider.d.ts +24 -0
  56. package/build/types/packages/react-query/src/QueryErrorResetBoundary.d.ts +12 -0
  57. package/build/types/packages/react-query/src/__tests__/Hydrate.test.d.ts +1 -0
  58. package/build/types/packages/react-query/src/__tests__/QueryClientProvider.test.d.ts +1 -0
  59. package/build/types/packages/react-query/src/__tests__/QueryResetErrorBoundary.test.d.ts +6 -0
  60. package/build/types/packages/react-query/src/__tests__/ssr-hydration.test.d.ts +1 -0
  61. package/build/types/packages/react-query/src/__tests__/ssr.test.d.ts +4 -0
  62. package/build/types/packages/react-query/src/__tests__/suspense.test.d.ts +1 -0
  63. package/build/types/packages/react-query/src/__tests__/useInfiniteQuery.test.d.ts +1 -0
  64. package/build/types/packages/react-query/src/__tests__/useIsFetching.test.d.ts +1 -0
  65. package/build/types/packages/react-query/src/__tests__/useIsMutating.test.d.ts +1 -0
  66. package/build/types/packages/react-query/src/__tests__/useMutation.test.d.ts +1 -0
  67. package/build/types/packages/react-query/src/__tests__/useQueries.test.d.ts +1 -0
  68. package/build/types/packages/react-query/src/__tests__/useQuery.test.d.ts +1 -0
  69. package/build/types/packages/react-query/src/__tests__/useQuery.types.test.d.ts +2 -0
  70. package/build/types/packages/react-query/src/__tests__/utils.d.ts +8 -0
  71. package/build/types/packages/react-query/src/index.d.ts +17 -0
  72. package/build/types/packages/react-query/src/isRestoring.d.ts +3 -0
  73. package/build/types/packages/react-query/src/reactBatchedUpdates.d.ts +2 -0
  74. package/build/types/packages/react-query/src/reactBatchedUpdates.native.d.ts +2 -0
  75. package/build/types/packages/react-query/src/setBatchUpdatesFn.d.ts +1 -0
  76. package/build/types/packages/react-query/src/types.d.ts +35 -0
  77. package/build/types/packages/react-query/src/useBaseQuery.d.ts +3 -0
  78. package/build/types/packages/react-query/src/useInfiniteQuery.d.ts +5 -0
  79. package/build/types/packages/react-query/src/useIsFetching.d.ts +7 -0
  80. package/build/types/packages/react-query/src/useIsMutating.d.ts +7 -0
  81. package/build/types/packages/react-query/src/useMutation.d.ts +6 -0
  82. package/build/types/packages/react-query/src/useQueries.d.ts +49 -0
  83. package/build/types/packages/react-query/src/useQuery.d.ts +20 -0
  84. package/build/types/packages/react-query/src/utils.d.ts +1 -0
  85. package/build/types/tests/utils.d.ts +24 -0
  86. package/build/umd/index.development.js +3429 -0
  87. package/build/umd/index.development.js.map +1 -0
  88. package/build/umd/index.production.js +22 -0
  89. package/build/umd/index.production.js.map +1 -0
  90. package/codemods/v4/key-transformation.js +138 -0
  91. package/codemods/v4/replace-import-specifier.js +25 -0
  92. package/codemods/v4/utils/index.js +166 -0
  93. package/codemods/v4/utils/replacers/key-replacer.js +160 -0
  94. package/codemods/v4/utils/transformers/query-cache-transformer.js +115 -0
  95. package/codemods/v4/utils/transformers/query-client-transformer.js +49 -0
  96. package/codemods/v4/utils/transformers/use-query-like-transformer.js +32 -0
  97. package/codemods/v4/utils/unprocessable-key-error.js +8 -0
  98. package/package.json +63 -0
  99. package/src/Hydrate.tsx +36 -0
  100. package/src/QueryClientProvider.tsx +90 -0
  101. package/src/QueryErrorResetBoundary.tsx +52 -0
  102. package/src/__tests__/Hydrate.test.tsx +247 -0
  103. package/src/__tests__/QueryClientProvider.test.tsx +275 -0
  104. package/src/__tests__/QueryResetErrorBoundary.test.tsx +630 -0
  105. package/src/__tests__/ssr-hydration.test.tsx +274 -0
  106. package/src/__tests__/ssr.test.tsx +151 -0
  107. package/src/__tests__/suspense.test.tsx +1015 -0
  108. package/src/__tests__/useInfiniteQuery.test.tsx +1773 -0
  109. package/src/__tests__/useIsFetching.test.tsx +274 -0
  110. package/src/__tests__/useIsMutating.test.tsx +260 -0
  111. package/src/__tests__/useMutation.test.tsx +1099 -0
  112. package/src/__tests__/useQueries.test.tsx +1107 -0
  113. package/src/__tests__/useQuery.test.tsx +5746 -0
  114. package/src/__tests__/useQuery.types.test.tsx +157 -0
  115. package/src/__tests__/utils.tsx +45 -0
  116. package/src/index.ts +29 -0
  117. package/src/isRestoring.tsx +6 -0
  118. package/src/reactBatchedUpdates.native.ts +4 -0
  119. package/src/reactBatchedUpdates.ts +2 -0
  120. package/src/setBatchUpdatesFn.ts +4 -0
  121. package/src/types.ts +122 -0
  122. package/src/useBaseQuery.ts +140 -0
  123. package/src/useInfiniteQuery.ts +101 -0
  124. package/src/useIsFetching.ts +39 -0
  125. package/src/useIsMutating.ts +43 -0
  126. package/src/useMutation.ts +126 -0
  127. package/src/useQueries.ts +192 -0
  128. package/src/useQuery.ts +104 -0
  129. 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
+ })