@tanstack/react-query 5.0.0-alpha.4 → 5.0.0-alpha.43
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/codemods/__testfixtures__/default-import.input.tsx +94 -0
- package/build/codemods/__testfixtures__/default-import.output.tsx +96 -0
- package/build/codemods/__testfixtures__/named-import.input.tsx +96 -0
- package/build/codemods/__testfixtures__/named-import.output.tsx +98 -0
- package/build/codemods/__testfixtures__/namespaced-import.input.tsx +86 -0
- package/build/codemods/__testfixtures__/namespaced-import.output.tsx +88 -0
- package/build/codemods/__testfixtures__/parameter-is-identifier.input.tsx +49 -0
- package/build/codemods/__testfixtures__/parameter-is-identifier.output.tsx +49 -0
- package/build/codemods/__testfixtures__/parameter-is-object-expression.input.tsx +128 -0
- package/build/codemods/__testfixtures__/parameter-is-object-expression.output.tsx +175 -0
- package/build/codemods/__testfixtures__/replace-import-specifier.input.tsx +10 -0
- package/build/codemods/__testfixtures__/replace-import-specifier.output.tsx +10 -0
- package/build/codemods/__testfixtures__/type-arguments.input.tsx +25 -0
- package/build/codemods/__testfixtures__/type-arguments.output.tsx +31 -0
- package/build/codemods/__tests__/key-transformation.test.js +32 -0
- package/build/codemods/__tests__/replace-import-specifier.test.js +12 -0
- package/build/codemods/remove-overloads/__testfixtures__/default-import.input.tsx +199 -0
- package/build/codemods/remove-overloads/__testfixtures__/default-import.output.tsx +484 -0
- package/build/codemods/remove-overloads/__tests__/remove-overloads.test.js +6 -0
- package/build/codemods/remove-overloads/remove-overloads.js +59 -0
- package/build/codemods/remove-overloads/transformers/filter-aware-usage-transformer.js +153 -0
- package/build/codemods/remove-overloads/transformers/query-fn-aware-usage-transformer.js +188 -0
- package/build/codemods/remove-overloads/utils/index.js +124 -0
- package/build/codemods/remove-overloads/utils/unknown-usage-error.js +26 -0
- package/build/codemods/src/utils/index.js +205 -0
- package/build/codemods/src/v4/key-transformation.js +138 -0
- package/build/codemods/src/v4/replace-import-specifier.js +25 -0
- package/build/codemods/transformers/query-cache-transformer.js +116 -0
- package/build/codemods/transformers/query-client-transformer.js +48 -0
- package/build/codemods/transformers/use-query-like-transformer.js +32 -0
- package/build/codemods/utils/replacers/key-replacer.js +164 -0
- package/build/lib/HydrationBoundary.d.ts +1 -0
- package/build/lib/HydrationBoundary.d.ts.map +1 -0
- package/build/lib/HydrationBoundary.esm.js +1 -0
- package/build/lib/HydrationBoundary.esm.js.map +1 -1
- package/build/lib/HydrationBoundary.js +1 -0
- package/build/lib/HydrationBoundary.js.map +1 -1
- package/build/lib/HydrationBoundary.mjs +1 -0
- package/build/lib/HydrationBoundary.mjs.map +1 -1
- package/build/lib/QueryClientProvider.d.ts +2 -1
- package/build/lib/QueryClientProvider.d.ts.map +1 -0
- package/build/lib/QueryClientProvider.esm.js +1 -0
- package/build/lib/QueryClientProvider.esm.js.map +1 -1
- package/build/lib/QueryClientProvider.js +1 -0
- package/build/lib/QueryClientProvider.js.map +1 -1
- package/build/lib/QueryClientProvider.mjs +1 -0
- package/build/lib/QueryClientProvider.mjs.map +1 -1
- package/build/lib/QueryErrorResetBoundary.d.ts +2 -1
- package/build/lib/QueryErrorResetBoundary.d.ts.map +1 -0
- package/build/lib/QueryErrorResetBoundary.esm.js +1 -0
- package/build/lib/QueryErrorResetBoundary.esm.js.map +1 -1
- package/build/lib/QueryErrorResetBoundary.js +1 -0
- package/build/lib/QueryErrorResetBoundary.js.map +1 -1
- package/build/lib/QueryErrorResetBoundary.mjs +1 -0
- package/build/lib/QueryErrorResetBoundary.mjs.map +1 -1
- package/build/lib/__tests__/HydrationBoundary.test.d.ts +1 -0
- package/build/lib/__tests__/HydrationBoundary.test.d.ts.map +1 -0
- package/build/lib/__tests__/QueryClientProvider.test.d.ts +1 -0
- package/build/lib/__tests__/QueryClientProvider.test.d.ts.map +1 -0
- package/build/lib/__tests__/QueryResetErrorBoundary.test.d.ts +1 -0
- package/build/lib/__tests__/QueryResetErrorBoundary.test.d.ts.map +1 -0
- package/build/lib/__tests__/ssr-hydration.test.d.ts +1 -0
- package/build/lib/__tests__/ssr-hydration.test.d.ts.map +1 -0
- package/build/lib/__tests__/ssr.test.d.ts +1 -3
- package/build/lib/__tests__/ssr.test.d.ts.map +1 -0
- package/build/lib/__tests__/suspense.test.d.ts +1 -0
- package/build/lib/__tests__/suspense.test.d.ts.map +1 -0
- package/build/lib/__tests__/useInfiniteQuery.test.d.ts +1 -0
- package/build/lib/__tests__/useInfiniteQuery.test.d.ts.map +1 -0
- package/build/lib/__tests__/useInfiniteQuery.type.test.d.ts +1 -0
- package/build/lib/__tests__/useInfiniteQuery.type.test.d.ts.map +1 -0
- package/build/lib/__tests__/useIsFetching.test.d.ts +1 -0
- package/build/lib/__tests__/useIsFetching.test.d.ts.map +1 -0
- package/build/lib/__tests__/useMutation.test.d.ts +1 -0
- package/build/lib/__tests__/useMutation.test.d.ts.map +1 -0
- package/build/lib/__tests__/useMutationState.test.d.ts +1 -0
- package/build/lib/__tests__/useMutationState.test.d.ts.map +1 -0
- package/build/lib/__tests__/useQueries.test.d.ts +1 -0
- package/build/lib/__tests__/useQueries.test.d.ts.map +1 -0
- package/build/lib/__tests__/useQuery.test.d.ts +1 -0
- package/build/lib/__tests__/useQuery.test.d.ts.map +1 -0
- package/build/lib/__tests__/useQuery.types.test.d.ts +1 -0
- package/build/lib/__tests__/useQuery.types.test.d.ts.map +1 -0
- package/build/lib/__tests__/utils.d.ts +6 -6
- package/build/lib/__tests__/utils.d.ts.map +1 -0
- package/build/lib/errorBoundaryUtils.d.ts +4 -3
- package/build/lib/errorBoundaryUtils.d.ts.map +1 -0
- package/build/lib/errorBoundaryUtils.esm.js +4 -3
- package/build/lib/errorBoundaryUtils.esm.js.map +1 -1
- package/build/lib/errorBoundaryUtils.js +4 -3
- package/build/lib/errorBoundaryUtils.js.map +1 -1
- package/build/lib/errorBoundaryUtils.mjs +4 -3
- package/build/lib/errorBoundaryUtils.mjs.map +1 -1
- package/build/lib/index.d.ts +2 -1
- package/build/lib/index.d.ts.map +1 -0
- package/build/lib/index.esm.js +1 -1
- package/build/lib/index.js +1 -0
- package/build/lib/index.js.map +1 -1
- package/build/lib/index.mjs +1 -1
- package/build/lib/isRestoring.d.ts +1 -0
- package/build/lib/isRestoring.d.ts.map +1 -0
- package/build/lib/isRestoring.esm.js +1 -0
- package/build/lib/isRestoring.esm.js.map +1 -1
- package/build/lib/isRestoring.js +1 -0
- package/build/lib/isRestoring.js.map +1 -1
- package/build/lib/isRestoring.mjs +1 -0
- package/build/lib/isRestoring.mjs.map +1 -1
- package/build/lib/suspense.d.ts +3 -5
- package/build/lib/suspense.d.ts.map +1 -0
- package/build/lib/suspense.esm.js +2 -9
- package/build/lib/suspense.esm.js.map +1 -1
- package/build/lib/suspense.js +2 -9
- package/build/lib/suspense.js.map +1 -1
- package/build/lib/suspense.mjs +1 -8
- package/build/lib/suspense.mjs.map +1 -1
- package/build/lib/types.d.ts +11 -10
- package/build/lib/types.d.ts.map +1 -0
- package/build/lib/useBaseQuery.d.ts +1 -0
- package/build/lib/useBaseQuery.d.ts.map +1 -0
- package/build/lib/useBaseQuery.esm.js +2 -12
- package/build/lib/useBaseQuery.esm.js.map +1 -1
- package/build/lib/useBaseQuery.js +2 -12
- package/build/lib/useBaseQuery.js.map +1 -1
- package/build/lib/useBaseQuery.mjs +2 -12
- package/build/lib/useBaseQuery.mjs.map +1 -1
- package/build/lib/useInfiniteQuery.d.ts +1 -0
- package/build/lib/useInfiniteQuery.d.ts.map +1 -0
- package/build/lib/useInfiniteQuery.esm.js +1 -0
- package/build/lib/useInfiniteQuery.esm.js.map +1 -1
- package/build/lib/useInfiniteQuery.js +1 -0
- package/build/lib/useInfiniteQuery.js.map +1 -1
- package/build/lib/useInfiniteQuery.mjs +1 -0
- package/build/lib/useInfiniteQuery.mjs.map +1 -1
- package/build/lib/useIsFetching.d.ts +1 -0
- package/build/lib/useIsFetching.d.ts.map +1 -0
- package/build/lib/useIsFetching.esm.js +1 -0
- package/build/lib/useIsFetching.esm.js.map +1 -1
- package/build/lib/useIsFetching.js +1 -0
- package/build/lib/useIsFetching.js.map +1 -1
- package/build/lib/useIsFetching.mjs +1 -0
- package/build/lib/useIsFetching.mjs.map +1 -1
- package/build/lib/useMutation.d.ts +1 -0
- package/build/lib/useMutation.d.ts.map +1 -0
- package/build/lib/useMutation.esm.js +2 -1
- package/build/lib/useMutation.esm.js.map +1 -1
- package/build/lib/useMutation.js +2 -1
- package/build/lib/useMutation.js.map +1 -1
- package/build/lib/useMutation.mjs +2 -1
- package/build/lib/useMutation.mjs.map +1 -1
- package/build/lib/useMutationState.d.ts +4 -3
- package/build/lib/useMutationState.d.ts.map +1 -0
- package/build/lib/useMutationState.esm.js +1 -0
- package/build/lib/useMutationState.esm.js.map +1 -1
- package/build/lib/useMutationState.js +1 -0
- package/build/lib/useMutationState.js.map +1 -1
- package/build/lib/useMutationState.mjs +1 -0
- package/build/lib/useMutationState.mjs.map +1 -1
- package/build/lib/useQueries.d.ts +10 -8
- package/build/lib/useQueries.d.ts.map +1 -0
- package/build/lib/useQueries.esm.js +39 -27
- package/build/lib/useQueries.esm.js.map +1 -1
- package/build/lib/useQueries.js +39 -27
- package/build/lib/useQueries.js.map +1 -1
- package/build/lib/useQueries.mjs +31 -22
- package/build/lib/useQueries.mjs.map +1 -1
- package/build/lib/useQuery.d.ts +5 -2
- package/build/lib/useQuery.d.ts.map +1 -0
- package/build/lib/useQuery.esm.js +6 -1
- package/build/lib/useQuery.esm.js.map +1 -1
- package/build/lib/useQuery.js +6 -0
- package/build/lib/useQuery.js.map +1 -1
- package/build/lib/useQuery.mjs +6 -1
- package/build/lib/useQuery.mjs.map +1 -1
- package/build/lib/utils.d.ts +1 -0
- package/build/lib/utils.d.ts.map +1 -0
- package/build/lib/utils.esm.js.map +1 -1
- package/build/lib/utils.js.map +1 -1
- package/build/lib/utils.mjs.map +1 -1
- package/build/umd/index.development.js +191 -187
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +13 -6
- package/src/__tests__/HydrationBoundary.test.tsx +4 -3
- package/src/__tests__/QueryClientProvider.test.tsx +2 -1
- package/src/__tests__/QueryResetErrorBoundary.test.tsx +753 -620
- package/src/__tests__/ssr-hydration.test.tsx +11 -10
- package/src/__tests__/ssr.test.tsx +4 -7
- package/src/__tests__/suspense.test.tsx +17 -98
- package/src/__tests__/useInfiniteQuery.test.tsx +18 -16
- package/src/__tests__/useInfiniteQuery.type.test.tsx +94 -13
- package/src/__tests__/useMutation.test.tsx +25 -24
- package/src/__tests__/useMutationState.test.tsx +24 -58
- package/src/__tests__/useQueries.test.tsx +217 -154
- package/src/__tests__/useQuery.test.tsx +234 -365
- package/src/__tests__/useQuery.types.test.tsx +21 -1
- package/src/__tests__/utils.tsx +3 -2
- package/src/errorBoundaryUtils.ts +6 -5
- package/src/index.ts +1 -1
- package/src/suspense.ts +9 -15
- package/src/useBaseQuery.ts +2 -20
- package/src/useInfiniteQuery.ts +1 -0
- package/src/useIsFetching.ts +1 -0
- package/src/useMutation.ts +2 -1
- package/src/useMutationState.ts +4 -3
- package/src/useQueries.ts +44 -26
- package/src/useQuery.ts +23 -0
|
@@ -3,7 +3,8 @@ import { ErrorBoundary } from 'react-error-boundary'
|
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
|
|
5
5
|
import { createQueryClient, queryKey, renderWithClient, sleep } from './utils'
|
|
6
|
-
import { QueryCache, QueryErrorResetBoundary, useQuery } from '..'
|
|
6
|
+
import { QueryCache, QueryErrorResetBoundary, useQuery, useQueries } from '..'
|
|
7
|
+
import { vi } from 'vitest'
|
|
7
8
|
|
|
8
9
|
// TODO: This should be removed with the types for react-error-boundary get updated.
|
|
9
10
|
declare module 'react-error-boundary' {
|
|
@@ -16,647 +17,779 @@ describe('QueryErrorResetBoundary', () => {
|
|
|
16
17
|
const queryCache = new QueryCache()
|
|
17
18
|
const queryClient = createQueryClient({ queryCache })
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<div>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
consoleMock.mockRestore()
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('should not throw error if query is disabled', async () => {
|
|
78
|
-
const consoleMock = jest
|
|
79
|
-
.spyOn(console, 'error')
|
|
80
|
-
.mockImplementation(() => undefined)
|
|
81
|
-
const key = queryKey()
|
|
82
|
-
|
|
83
|
-
let succeed = false
|
|
84
|
-
|
|
85
|
-
function Page() {
|
|
86
|
-
const { data, status } = useQuery({
|
|
87
|
-
queryKey: key,
|
|
88
|
-
queryFn: async () => {
|
|
89
|
-
await sleep(10)
|
|
90
|
-
if (!succeed) {
|
|
91
|
-
throw new Error('Error')
|
|
92
|
-
} else {
|
|
93
|
-
return 'data'
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
retry: false,
|
|
97
|
-
enabled: !succeed,
|
|
98
|
-
throwErrors: true,
|
|
99
|
-
})
|
|
100
|
-
return (
|
|
101
|
-
<div>
|
|
102
|
-
<div>status: {status}</div>
|
|
103
|
-
<div>{data}</div>
|
|
104
|
-
</div>
|
|
20
|
+
describe('useQuery', () => {
|
|
21
|
+
it('should retry fetch if the reset error boundary has been reset', async () => {
|
|
22
|
+
const consoleMock = vi
|
|
23
|
+
.spyOn(console, 'error')
|
|
24
|
+
.mockImplementation(() => undefined)
|
|
25
|
+
const key = queryKey()
|
|
26
|
+
|
|
27
|
+
let succeed = false
|
|
28
|
+
|
|
29
|
+
function Page() {
|
|
30
|
+
const { data } = useQuery({
|
|
31
|
+
queryKey: key,
|
|
32
|
+
queryFn: async () => {
|
|
33
|
+
await sleep(10)
|
|
34
|
+
if (!succeed) {
|
|
35
|
+
throw new Error('Error')
|
|
36
|
+
} else {
|
|
37
|
+
return 'data'
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
retry: false,
|
|
41
|
+
throwOnError: true,
|
|
42
|
+
})
|
|
43
|
+
return <div>{data}</div>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const rendered = renderWithClient(
|
|
47
|
+
queryClient,
|
|
48
|
+
<QueryErrorResetBoundary>
|
|
49
|
+
{({ reset }) => (
|
|
50
|
+
<ErrorBoundary
|
|
51
|
+
onReset={reset}
|
|
52
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
53
|
+
<div>
|
|
54
|
+
<div>error boundary</div>
|
|
55
|
+
<button
|
|
56
|
+
onClick={() => {
|
|
57
|
+
resetErrorBoundary()
|
|
58
|
+
}}
|
|
59
|
+
>
|
|
60
|
+
retry
|
|
61
|
+
</button>
|
|
62
|
+
</div>
|
|
63
|
+
)}
|
|
64
|
+
>
|
|
65
|
+
<Page />
|
|
66
|
+
</ErrorBoundary>
|
|
67
|
+
)}
|
|
68
|
+
</QueryErrorResetBoundary>,
|
|
105
69
|
)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const rendered = renderWithClient(
|
|
109
|
-
queryClient,
|
|
110
|
-
<QueryErrorResetBoundary>
|
|
111
|
-
{({ reset }) => (
|
|
112
|
-
<ErrorBoundary
|
|
113
|
-
onReset={reset}
|
|
114
|
-
fallbackRender={({ resetErrorBoundary }) => (
|
|
115
|
-
<div>
|
|
116
|
-
<div>error boundary</div>
|
|
117
|
-
<button
|
|
118
|
-
onClick={() => {
|
|
119
|
-
resetErrorBoundary()
|
|
120
|
-
}}
|
|
121
|
-
>
|
|
122
|
-
retry
|
|
123
|
-
</button>
|
|
124
|
-
</div>
|
|
125
|
-
)}
|
|
126
|
-
>
|
|
127
|
-
<Page />
|
|
128
|
-
</ErrorBoundary>
|
|
129
|
-
)}
|
|
130
|
-
</QueryErrorResetBoundary>,
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
await waitFor(() => rendered.getByText('error boundary'))
|
|
134
|
-
await waitFor(() => rendered.getByText('retry'))
|
|
135
|
-
succeed = true
|
|
136
|
-
fireEvent.click(rendered.getByText('retry'))
|
|
137
|
-
await waitFor(() => rendered.getByText('status: error'))
|
|
138
|
-
consoleMock.mockRestore()
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
it('should not throw error if query is disabled, and refetch if query becomes enabled again', async () => {
|
|
142
|
-
const consoleMock = jest
|
|
143
|
-
.spyOn(console, 'error')
|
|
144
|
-
.mockImplementation(() => undefined)
|
|
145
|
-
|
|
146
|
-
const key = queryKey()
|
|
147
70
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
fallbackRender={({ resetErrorBoundary }) => (
|
|
181
|
-
<div>
|
|
182
|
-
<div>error boundary</div>
|
|
183
|
-
<button
|
|
184
|
-
onClick={() => {
|
|
185
|
-
resetErrorBoundary()
|
|
186
|
-
}}
|
|
187
|
-
>
|
|
188
|
-
retry
|
|
189
|
-
</button>
|
|
190
|
-
</div>
|
|
191
|
-
)}
|
|
192
|
-
>
|
|
193
|
-
<Page />
|
|
194
|
-
</ErrorBoundary>
|
|
195
|
-
)}
|
|
196
|
-
</QueryErrorResetBoundary>,
|
|
197
|
-
)
|
|
198
|
-
|
|
199
|
-
await waitFor(() => rendered.getByText('error boundary'))
|
|
200
|
-
await waitFor(() => rendered.getByText('retry'))
|
|
201
|
-
succeed = true
|
|
202
|
-
fireEvent.click(rendered.getByText('retry'))
|
|
203
|
-
await waitFor(() => rendered.getByText('data'))
|
|
204
|
-
consoleMock.mockRestore()
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
it('should throw error if query is disabled and manually refetched', async () => {
|
|
208
|
-
const consoleMock = jest
|
|
209
|
-
.spyOn(console, 'error')
|
|
210
|
-
.mockImplementation(() => undefined)
|
|
211
|
-
|
|
212
|
-
const key = queryKey()
|
|
213
|
-
|
|
214
|
-
function Page() {
|
|
215
|
-
const { data, refetch, status, fetchStatus } = useQuery<string>({
|
|
216
|
-
queryKey: key,
|
|
217
|
-
queryFn: async () => {
|
|
218
|
-
throw new Error('Error')
|
|
219
|
-
},
|
|
220
|
-
retry: false,
|
|
221
|
-
enabled: false,
|
|
222
|
-
throwErrors: true,
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
return (
|
|
226
|
-
<div>
|
|
227
|
-
<button onClick={() => refetch()}>refetch</button>
|
|
71
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
72
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
73
|
+
succeed = true
|
|
74
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
75
|
+
await waitFor(() => rendered.getByText('data'))
|
|
76
|
+
consoleMock.mockRestore()
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('should not throw error if query is disabled', async () => {
|
|
80
|
+
const consoleMock = vi
|
|
81
|
+
.spyOn(console, 'error')
|
|
82
|
+
.mockImplementation(() => undefined)
|
|
83
|
+
const key = queryKey()
|
|
84
|
+
|
|
85
|
+
let succeed = false
|
|
86
|
+
|
|
87
|
+
function Page() {
|
|
88
|
+
const { data, status } = useQuery({
|
|
89
|
+
queryKey: key,
|
|
90
|
+
queryFn: async () => {
|
|
91
|
+
await sleep(10)
|
|
92
|
+
if (!succeed) {
|
|
93
|
+
throw new Error('Error')
|
|
94
|
+
} else {
|
|
95
|
+
return 'data'
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
retry: false,
|
|
99
|
+
enabled: !succeed,
|
|
100
|
+
throwOnError: true,
|
|
101
|
+
})
|
|
102
|
+
return (
|
|
228
103
|
<div>
|
|
229
|
-
status: {status}
|
|
104
|
+
<div>status: {status}</div>
|
|
105
|
+
<div>{data}</div>
|
|
230
106
|
</div>
|
|
231
|
-
|
|
232
|
-
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const rendered = renderWithClient(
|
|
111
|
+
queryClient,
|
|
112
|
+
<QueryErrorResetBoundary>
|
|
113
|
+
{({ reset }) => (
|
|
114
|
+
<ErrorBoundary
|
|
115
|
+
onReset={reset}
|
|
116
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
117
|
+
<div>
|
|
118
|
+
<div>error boundary</div>
|
|
119
|
+
<button
|
|
120
|
+
onClick={() => {
|
|
121
|
+
resetErrorBoundary()
|
|
122
|
+
}}
|
|
123
|
+
>
|
|
124
|
+
retry
|
|
125
|
+
</button>
|
|
126
|
+
</div>
|
|
127
|
+
)}
|
|
128
|
+
>
|
|
129
|
+
<Page />
|
|
130
|
+
</ErrorBoundary>
|
|
131
|
+
)}
|
|
132
|
+
</QueryErrorResetBoundary>,
|
|
233
133
|
)
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
const rendered = renderWithClient(
|
|
237
|
-
queryClient,
|
|
238
|
-
<QueryErrorResetBoundary>
|
|
239
|
-
{({ reset }) => (
|
|
240
|
-
<ErrorBoundary
|
|
241
|
-
onReset={reset}
|
|
242
|
-
fallbackRender={({ resetErrorBoundary }) => (
|
|
243
|
-
<div>
|
|
244
|
-
<div>error boundary</div>
|
|
245
|
-
<button
|
|
246
|
-
onClick={() => {
|
|
247
|
-
resetErrorBoundary()
|
|
248
|
-
}}
|
|
249
|
-
>
|
|
250
|
-
retry
|
|
251
|
-
</button>
|
|
252
|
-
</div>
|
|
253
|
-
)}
|
|
254
|
-
>
|
|
255
|
-
<Page />
|
|
256
|
-
</ErrorBoundary>
|
|
257
|
-
)}
|
|
258
|
-
</QueryErrorResetBoundary>,
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
await waitFor(() =>
|
|
262
|
-
rendered.getByText('status: pending, fetchStatus: idle'),
|
|
263
|
-
)
|
|
264
|
-
fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))
|
|
265
|
-
await waitFor(() => rendered.getByText('error boundary'))
|
|
266
|
-
consoleMock.mockRestore()
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
it('should not retry fetch if the reset error boundary has not been reset', async () => {
|
|
270
|
-
const consoleMock = jest
|
|
271
|
-
.spyOn(console, 'error')
|
|
272
|
-
.mockImplementation(() => undefined)
|
|
273
|
-
|
|
274
|
-
const key = queryKey()
|
|
275
|
-
|
|
276
|
-
let succeed = false
|
|
277
|
-
|
|
278
|
-
function Page() {
|
|
279
|
-
const { data } = useQuery({
|
|
280
|
-
queryKey: key,
|
|
281
|
-
queryFn: async () => {
|
|
282
|
-
await sleep(10)
|
|
283
|
-
if (!succeed) {
|
|
284
|
-
throw new Error('Error')
|
|
285
|
-
} else {
|
|
286
|
-
return 'data'
|
|
287
|
-
}
|
|
288
|
-
},
|
|
289
|
-
retry: false,
|
|
290
|
-
throwErrors: true,
|
|
291
|
-
})
|
|
292
|
-
return <div>{data}</div>
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const rendered = renderWithClient(
|
|
296
|
-
queryClient,
|
|
297
|
-
<QueryErrorResetBoundary>
|
|
298
|
-
{() => (
|
|
299
|
-
<ErrorBoundary
|
|
300
|
-
fallbackRender={({ resetErrorBoundary }) => (
|
|
301
|
-
<div>
|
|
302
|
-
<div>error boundary</div>
|
|
303
|
-
<button
|
|
304
|
-
onClick={() => {
|
|
305
|
-
resetErrorBoundary()
|
|
306
|
-
}}
|
|
307
|
-
>
|
|
308
|
-
retry
|
|
309
|
-
</button>
|
|
310
|
-
</div>
|
|
311
|
-
)}
|
|
312
|
-
>
|
|
313
|
-
<Page />
|
|
314
|
-
</ErrorBoundary>
|
|
315
|
-
)}
|
|
316
|
-
</QueryErrorResetBoundary>,
|
|
317
|
-
)
|
|
318
|
-
|
|
319
|
-
await waitFor(() => rendered.getByText('error boundary'))
|
|
320
|
-
await waitFor(() => rendered.getByText('retry'))
|
|
321
|
-
succeed = true
|
|
322
|
-
fireEvent.click(rendered.getByText('retry'))
|
|
323
|
-
await waitFor(() => rendered.getByText('error boundary'))
|
|
324
|
-
consoleMock.mockRestore()
|
|
325
|
-
})
|
|
326
|
-
|
|
327
|
-
it('should retry fetch if the reset error boundary has been reset and the query contains data from a previous fetch', async () => {
|
|
328
|
-
const consoleMock = jest
|
|
329
|
-
.spyOn(console, 'error')
|
|
330
|
-
.mockImplementation(() => undefined)
|
|
331
|
-
|
|
332
|
-
const key = queryKey()
|
|
333
134
|
|
|
334
|
-
|
|
135
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
136
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
137
|
+
succeed = true
|
|
138
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
139
|
+
await waitFor(() => rendered.getByText('status: error'))
|
|
140
|
+
consoleMock.mockRestore()
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
it('should not throw error if query is disabled, and refetch if query becomes enabled again', async () => {
|
|
144
|
+
const consoleMock = vi
|
|
145
|
+
.spyOn(console, 'error')
|
|
146
|
+
.mockImplementation(() => undefined)
|
|
147
|
+
|
|
148
|
+
const key = queryKey()
|
|
149
|
+
|
|
150
|
+
let succeed = false
|
|
151
|
+
|
|
152
|
+
function Page() {
|
|
153
|
+
const [enabled, setEnabled] = React.useState(false)
|
|
154
|
+
const { data } = useQuery({
|
|
155
|
+
queryKey: key,
|
|
156
|
+
queryFn: async () => {
|
|
157
|
+
await sleep(10)
|
|
158
|
+
if (!succeed) {
|
|
159
|
+
throw new Error('Error')
|
|
160
|
+
} else {
|
|
161
|
+
return 'data'
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
retry: false,
|
|
165
|
+
enabled,
|
|
166
|
+
throwOnError: true,
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
React.useEffect(() => {
|
|
170
|
+
setEnabled(true)
|
|
171
|
+
}, [])
|
|
172
|
+
|
|
173
|
+
return <div>{data}</div>
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const rendered = renderWithClient(
|
|
177
|
+
queryClient,
|
|
178
|
+
<QueryErrorResetBoundary>
|
|
179
|
+
{({ reset }) => (
|
|
180
|
+
<ErrorBoundary
|
|
181
|
+
onReset={reset}
|
|
182
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
183
|
+
<div>
|
|
184
|
+
<div>error boundary</div>
|
|
185
|
+
<button
|
|
186
|
+
onClick={() => {
|
|
187
|
+
resetErrorBoundary()
|
|
188
|
+
}}
|
|
189
|
+
>
|
|
190
|
+
retry
|
|
191
|
+
</button>
|
|
192
|
+
</div>
|
|
193
|
+
)}
|
|
194
|
+
>
|
|
195
|
+
<Page />
|
|
196
|
+
</ErrorBoundary>
|
|
197
|
+
)}
|
|
198
|
+
</QueryErrorResetBoundary>,
|
|
199
|
+
)
|
|
335
200
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
201
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
202
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
203
|
+
succeed = true
|
|
204
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
205
|
+
await waitFor(() => rendered.getByText('data'))
|
|
206
|
+
consoleMock.mockRestore()
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
it('should throw error if query is disabled and manually refetched', async () => {
|
|
210
|
+
const consoleMock = vi
|
|
211
|
+
.spyOn(console, 'error')
|
|
212
|
+
.mockImplementation(() => undefined)
|
|
213
|
+
|
|
214
|
+
const key = queryKey()
|
|
215
|
+
|
|
216
|
+
function Page() {
|
|
217
|
+
const { data, refetch, status, fetchStatus } = useQuery<string>({
|
|
218
|
+
queryKey: key,
|
|
219
|
+
queryFn: async () => {
|
|
342
220
|
throw new Error('Error')
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
throwErrors: true,
|
|
349
|
-
initialData: 'initial',
|
|
350
|
-
})
|
|
351
|
-
return <div>{data}</div>
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
const rendered = renderWithClient(
|
|
355
|
-
queryClient,
|
|
356
|
-
<QueryErrorResetBoundary>
|
|
357
|
-
{({ reset }) => (
|
|
358
|
-
<ErrorBoundary
|
|
359
|
-
onReset={reset}
|
|
360
|
-
fallbackRender={({ resetErrorBoundary }) => (
|
|
361
|
-
<div>
|
|
362
|
-
<div>error boundary</div>
|
|
363
|
-
<button
|
|
364
|
-
onClick={() => {
|
|
365
|
-
resetErrorBoundary()
|
|
366
|
-
}}
|
|
367
|
-
>
|
|
368
|
-
retry
|
|
369
|
-
</button>
|
|
370
|
-
</div>
|
|
371
|
-
)}
|
|
372
|
-
>
|
|
373
|
-
<Page />
|
|
374
|
-
</ErrorBoundary>
|
|
375
|
-
)}
|
|
376
|
-
</QueryErrorResetBoundary>,
|
|
377
|
-
)
|
|
378
|
-
|
|
379
|
-
await waitFor(() => rendered.getByText('error boundary'))
|
|
380
|
-
await waitFor(() => rendered.getByText('retry'))
|
|
381
|
-
succeed = true
|
|
382
|
-
fireEvent.click(rendered.getByText('retry'))
|
|
383
|
-
await waitFor(() => rendered.getByText('data'))
|
|
384
|
-
consoleMock.mockRestore()
|
|
385
|
-
})
|
|
221
|
+
},
|
|
222
|
+
retry: false,
|
|
223
|
+
enabled: false,
|
|
224
|
+
throwOnError: true,
|
|
225
|
+
})
|
|
386
226
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
227
|
+
return (
|
|
228
|
+
<div>
|
|
229
|
+
<button onClick={() => refetch()}>refetch</button>
|
|
230
|
+
<div>
|
|
231
|
+
status: {status}, fetchStatus: {fetchStatus}
|
|
232
|
+
</div>
|
|
233
|
+
<div>{data}</div>
|
|
234
|
+
</div>
|
|
235
|
+
)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const rendered = renderWithClient(
|
|
239
|
+
queryClient,
|
|
240
|
+
<QueryErrorResetBoundary>
|
|
241
|
+
{({ reset }) => (
|
|
242
|
+
<ErrorBoundary
|
|
243
|
+
onReset={reset}
|
|
244
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
245
|
+
<div>
|
|
246
|
+
<div>error boundary</div>
|
|
247
|
+
<button
|
|
248
|
+
onClick={() => {
|
|
249
|
+
resetErrorBoundary()
|
|
250
|
+
}}
|
|
251
|
+
>
|
|
252
|
+
retry
|
|
253
|
+
</button>
|
|
254
|
+
</div>
|
|
255
|
+
)}
|
|
256
|
+
>
|
|
257
|
+
<Page />
|
|
258
|
+
</ErrorBoundary>
|
|
259
|
+
)}
|
|
260
|
+
</QueryErrorResetBoundary>,
|
|
261
|
+
)
|
|
393
262
|
|
|
394
|
-
|
|
395
|
-
|
|
263
|
+
await waitFor(() =>
|
|
264
|
+
rendered.getByText('status: pending, fetchStatus: idle'),
|
|
265
|
+
)
|
|
266
|
+
fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))
|
|
267
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
268
|
+
consoleMock.mockRestore()
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
it('should not retry fetch if the reset error boundary has not been reset', async () => {
|
|
272
|
+
const consoleMock = vi
|
|
273
|
+
.spyOn(console, 'error')
|
|
274
|
+
.mockImplementation(() => undefined)
|
|
275
|
+
|
|
276
|
+
const key = queryKey()
|
|
277
|
+
|
|
278
|
+
let succeed = false
|
|
279
|
+
|
|
280
|
+
function Page() {
|
|
281
|
+
const { data } = useQuery({
|
|
282
|
+
queryKey: key,
|
|
283
|
+
queryFn: async () => {
|
|
284
|
+
await sleep(10)
|
|
285
|
+
if (!succeed) {
|
|
286
|
+
throw new Error('Error')
|
|
287
|
+
} else {
|
|
288
|
+
return 'data'
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
retry: false,
|
|
292
|
+
throwOnError: true,
|
|
293
|
+
})
|
|
294
|
+
return <div>{data}</div>
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const rendered = renderWithClient(
|
|
298
|
+
queryClient,
|
|
299
|
+
<QueryErrorResetBoundary>
|
|
300
|
+
{() => (
|
|
301
|
+
<ErrorBoundary
|
|
302
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
303
|
+
<div>
|
|
304
|
+
<div>error boundary</div>
|
|
305
|
+
<button
|
|
306
|
+
onClick={() => {
|
|
307
|
+
resetErrorBoundary()
|
|
308
|
+
}}
|
|
309
|
+
>
|
|
310
|
+
retry
|
|
311
|
+
</button>
|
|
312
|
+
</div>
|
|
313
|
+
)}
|
|
314
|
+
>
|
|
315
|
+
<Page />
|
|
316
|
+
</ErrorBoundary>
|
|
317
|
+
)}
|
|
318
|
+
</QueryErrorResetBoundary>,
|
|
319
|
+
)
|
|
396
320
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
321
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
322
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
323
|
+
succeed = true
|
|
324
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
325
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
326
|
+
consoleMock.mockRestore()
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
it('should retry fetch if the reset error boundary has been reset and the query contains data from a previous fetch', async () => {
|
|
330
|
+
const consoleMock = vi
|
|
331
|
+
.spyOn(console, 'error')
|
|
332
|
+
.mockImplementation(() => undefined)
|
|
333
|
+
|
|
334
|
+
const key = queryKey()
|
|
335
|
+
|
|
336
|
+
let succeed = false
|
|
337
|
+
|
|
338
|
+
function Page() {
|
|
339
|
+
const { data } = useQuery({
|
|
340
|
+
queryKey: key,
|
|
341
|
+
queryFn: async () => {
|
|
342
|
+
await sleep(10)
|
|
343
|
+
if (!succeed) {
|
|
344
|
+
throw new Error('Error')
|
|
345
|
+
} else {
|
|
346
|
+
return 'data'
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
retry: false,
|
|
350
|
+
throwOnError: true,
|
|
351
|
+
initialData: 'initial',
|
|
352
|
+
})
|
|
353
|
+
return <div>{data}</div>
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const rendered = renderWithClient(
|
|
357
|
+
queryClient,
|
|
358
|
+
<QueryErrorResetBoundary>
|
|
359
|
+
{({ reset }) => (
|
|
360
|
+
<ErrorBoundary
|
|
361
|
+
onReset={reset}
|
|
362
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
363
|
+
<div>
|
|
364
|
+
<div>error boundary</div>
|
|
365
|
+
<button
|
|
366
|
+
onClick={() => {
|
|
367
|
+
resetErrorBoundary()
|
|
368
|
+
}}
|
|
369
|
+
>
|
|
370
|
+
retry
|
|
371
|
+
</button>
|
|
372
|
+
</div>
|
|
373
|
+
)}
|
|
374
|
+
>
|
|
375
|
+
<Page />
|
|
376
|
+
</ErrorBoundary>
|
|
377
|
+
)}
|
|
378
|
+
</QueryErrorResetBoundary>,
|
|
379
|
+
)
|
|
454
380
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
.
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
const
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
381
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
382
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
383
|
+
succeed = true
|
|
384
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
385
|
+
await waitFor(() => rendered.getByText('data'))
|
|
386
|
+
consoleMock.mockRestore()
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
it('should not retry fetch if the reset error boundary has not been reset after a previous reset', async () => {
|
|
390
|
+
const consoleMock = vi
|
|
391
|
+
.spyOn(console, 'error')
|
|
392
|
+
.mockImplementation(() => undefined)
|
|
393
|
+
|
|
394
|
+
const key = queryKey()
|
|
395
|
+
|
|
396
|
+
let succeed = false
|
|
397
|
+
let shouldReset = true
|
|
398
|
+
|
|
399
|
+
function Page() {
|
|
400
|
+
const { data } = useQuery({
|
|
401
|
+
queryKey: key,
|
|
402
|
+
queryFn: async () => {
|
|
403
|
+
await sleep(10)
|
|
404
|
+
if (!succeed) {
|
|
405
|
+
throw new Error('Error')
|
|
406
|
+
} else {
|
|
407
|
+
return 'data'
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
retry: false,
|
|
411
|
+
throwOnError: true,
|
|
412
|
+
})
|
|
413
|
+
return <div>{data}</div>
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
const rendered = renderWithClient(
|
|
417
|
+
queryClient,
|
|
418
|
+
<QueryErrorResetBoundary>
|
|
419
|
+
{({ reset }) => (
|
|
420
|
+
<ErrorBoundary
|
|
421
|
+
onReset={() => {
|
|
422
|
+
if (shouldReset) {
|
|
423
|
+
reset()
|
|
424
|
+
}
|
|
425
|
+
}}
|
|
426
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
427
|
+
<div>
|
|
428
|
+
<div>error boundary</div>
|
|
429
|
+
<button
|
|
430
|
+
onClick={() => {
|
|
431
|
+
resetErrorBoundary()
|
|
432
|
+
}}
|
|
433
|
+
>
|
|
434
|
+
retry
|
|
435
|
+
</button>
|
|
436
|
+
</div>
|
|
437
|
+
)}
|
|
438
|
+
>
|
|
439
|
+
<Page />
|
|
440
|
+
</ErrorBoundary>
|
|
441
|
+
)}
|
|
442
|
+
</QueryErrorResetBoundary>,
|
|
443
|
+
)
|
|
512
444
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
.
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
445
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
446
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
447
|
+
shouldReset = true
|
|
448
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
449
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
450
|
+
succeed = true
|
|
451
|
+
shouldReset = false
|
|
452
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
453
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
454
|
+
consoleMock.mockRestore()
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
it('should throw again on error after the reset error boundary has been reset', async () => {
|
|
458
|
+
const consoleMock = vi
|
|
459
|
+
.spyOn(console, 'error')
|
|
460
|
+
.mockImplementation(() => undefined)
|
|
461
|
+
|
|
462
|
+
const key = queryKey()
|
|
463
|
+
let fetchCount = 0
|
|
464
|
+
|
|
465
|
+
function Page() {
|
|
466
|
+
const { data } = useQuery<string>({
|
|
467
|
+
queryKey: key,
|
|
468
|
+
queryFn: async () => {
|
|
469
|
+
fetchCount++
|
|
470
|
+
await sleep(10)
|
|
531
471
|
throw new Error('Error')
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
)}
|
|
559
|
-
>
|
|
560
|
-
<React.Suspense fallback={<div>loading</div>}>
|
|
472
|
+
},
|
|
473
|
+
retry: false,
|
|
474
|
+
throwOnError: true,
|
|
475
|
+
})
|
|
476
|
+
return <div>{data}</div>
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const rendered = renderWithClient(
|
|
480
|
+
queryClient,
|
|
481
|
+
<QueryErrorResetBoundary>
|
|
482
|
+
{({ reset }) => (
|
|
483
|
+
<ErrorBoundary
|
|
484
|
+
onReset={reset}
|
|
485
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
486
|
+
<div>
|
|
487
|
+
<div>error boundary</div>
|
|
488
|
+
<button
|
|
489
|
+
onClick={() => {
|
|
490
|
+
resetErrorBoundary()
|
|
491
|
+
}}
|
|
492
|
+
>
|
|
493
|
+
retry
|
|
494
|
+
</button>
|
|
495
|
+
</div>
|
|
496
|
+
)}
|
|
497
|
+
>
|
|
561
498
|
<Page />
|
|
562
|
-
</
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
)
|
|
567
|
-
|
|
568
|
-
await waitFor(() => rendered.getByText('error boundary'))
|
|
569
|
-
await waitFor(() => rendered.getByText('retry'))
|
|
570
|
-
fireEvent.click(rendered.getByText('retry'))
|
|
571
|
-
await waitFor(() => rendered.getByText('error boundary'))
|
|
572
|
-
await waitFor(() => rendered.getByText('retry'))
|
|
573
|
-
fireEvent.click(rendered.getByText('retry'))
|
|
574
|
-
await waitFor(() => rendered.getByText('data'))
|
|
575
|
-
expect(fetchCount).toBe(3)
|
|
576
|
-
expect(renders).toBe(1)
|
|
577
|
-
consoleMock.mockRestore()
|
|
578
|
-
})
|
|
499
|
+
</ErrorBoundary>
|
|
500
|
+
)}
|
|
501
|
+
</QueryErrorResetBoundary>,
|
|
502
|
+
)
|
|
579
503
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
.
|
|
583
|
-
|
|
504
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
505
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
506
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
507
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
508
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
509
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
510
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
511
|
+
expect(fetchCount).toBe(3)
|
|
512
|
+
consoleMock.mockRestore()
|
|
513
|
+
})
|
|
514
|
+
|
|
515
|
+
it('should never render the component while the query is in error state', async () => {
|
|
516
|
+
const consoleMock = vi
|
|
517
|
+
.spyOn(console, 'error')
|
|
518
|
+
.mockImplementation(() => undefined)
|
|
519
|
+
|
|
520
|
+
const key = queryKey()
|
|
521
|
+
let fetchCount = 0
|
|
522
|
+
let renders = 0
|
|
523
|
+
|
|
524
|
+
function Page() {
|
|
525
|
+
const { data } = useQuery({
|
|
526
|
+
queryKey: key,
|
|
527
|
+
queryFn: async () => {
|
|
528
|
+
fetchCount++
|
|
529
|
+
await sleep(10)
|
|
530
|
+
if (fetchCount > 2) {
|
|
531
|
+
return 'data'
|
|
532
|
+
} else {
|
|
533
|
+
throw new Error('Error')
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
retry: false,
|
|
537
|
+
suspense: true,
|
|
538
|
+
})
|
|
539
|
+
renders++
|
|
540
|
+
return <div>{data}</div>
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
const rendered = renderWithClient(
|
|
544
|
+
queryClient,
|
|
545
|
+
<QueryErrorResetBoundary>
|
|
546
|
+
{({ reset }) => (
|
|
547
|
+
<ErrorBoundary
|
|
548
|
+
onReset={reset}
|
|
549
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
550
|
+
<div>
|
|
551
|
+
<div>error boundary</div>
|
|
552
|
+
<button
|
|
553
|
+
onClick={() => {
|
|
554
|
+
resetErrorBoundary()
|
|
555
|
+
}}
|
|
556
|
+
>
|
|
557
|
+
retry
|
|
558
|
+
</button>
|
|
559
|
+
</div>
|
|
560
|
+
)}
|
|
561
|
+
>
|
|
562
|
+
<React.Suspense fallback={<div>loading</div>}>
|
|
563
|
+
<Page />
|
|
564
|
+
</React.Suspense>
|
|
565
|
+
</ErrorBoundary>
|
|
566
|
+
)}
|
|
567
|
+
</QueryErrorResetBoundary>,
|
|
568
|
+
)
|
|
584
569
|
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
570
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
571
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
572
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
573
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
574
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
575
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
576
|
+
await waitFor(() => rendered.getByText('data'))
|
|
577
|
+
expect(fetchCount).toBe(3)
|
|
578
|
+
expect(renders).toBe(1)
|
|
579
|
+
consoleMock.mockRestore()
|
|
580
|
+
})
|
|
581
|
+
|
|
582
|
+
it('should render children', async () => {
|
|
583
|
+
const consoleMock = vi
|
|
584
|
+
.spyOn(console, 'error')
|
|
585
|
+
.mockImplementation(() => undefined)
|
|
586
|
+
|
|
587
|
+
function Page() {
|
|
588
|
+
return (
|
|
589
|
+
<div>
|
|
590
|
+
<span>page</span>
|
|
591
|
+
</div>
|
|
592
|
+
)
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const rendered = renderWithClient(
|
|
596
|
+
queryClient,
|
|
597
|
+
<QueryErrorResetBoundary>
|
|
598
|
+
<Page />
|
|
599
|
+
</QueryErrorResetBoundary>,
|
|
590
600
|
)
|
|
591
|
-
}
|
|
592
601
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
602
|
+
expect(rendered.queryByText('page')).not.toBeNull()
|
|
603
|
+
consoleMock.mockRestore()
|
|
604
|
+
})
|
|
605
|
+
|
|
606
|
+
it('should show error boundary when using tracked queries even though we do not track the error field', async () => {
|
|
607
|
+
const consoleMock = vi
|
|
608
|
+
.spyOn(console, 'error')
|
|
609
|
+
.mockImplementation(() => undefined)
|
|
610
|
+
|
|
611
|
+
const key = queryKey()
|
|
612
|
+
|
|
613
|
+
let succeed = false
|
|
614
|
+
|
|
615
|
+
function Page() {
|
|
616
|
+
const { data } = useQuery({
|
|
617
|
+
queryKey: key,
|
|
618
|
+
queryFn: async () => {
|
|
619
|
+
await sleep(10)
|
|
620
|
+
if (!succeed) {
|
|
621
|
+
throw new Error('Error')
|
|
622
|
+
} else {
|
|
623
|
+
return 'data'
|
|
624
|
+
}
|
|
625
|
+
},
|
|
626
|
+
retry: false,
|
|
627
|
+
throwOnError: true,
|
|
628
|
+
})
|
|
629
|
+
return <div>{data}</div>
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
const rendered = renderWithClient(
|
|
633
|
+
queryClient,
|
|
634
|
+
<QueryErrorResetBoundary>
|
|
635
|
+
{({ reset }) => (
|
|
636
|
+
<ErrorBoundary
|
|
637
|
+
onReset={reset}
|
|
638
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
639
|
+
<div>
|
|
640
|
+
<div>error boundary</div>
|
|
641
|
+
<button
|
|
642
|
+
onClick={() => {
|
|
643
|
+
resetErrorBoundary()
|
|
644
|
+
}}
|
|
645
|
+
>
|
|
646
|
+
retry
|
|
647
|
+
</button>
|
|
648
|
+
</div>
|
|
649
|
+
)}
|
|
650
|
+
>
|
|
651
|
+
<Page />
|
|
652
|
+
</ErrorBoundary>
|
|
653
|
+
)}
|
|
654
|
+
</QueryErrorResetBoundary>,
|
|
655
|
+
)
|
|
599
656
|
|
|
600
|
-
|
|
601
|
-
|
|
657
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
658
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
659
|
+
succeed = true
|
|
660
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
661
|
+
await waitFor(() => rendered.getByText('data'))
|
|
662
|
+
consoleMock.mockRestore()
|
|
663
|
+
})
|
|
602
664
|
})
|
|
665
|
+
describe('useQueries', () => {
|
|
666
|
+
it('should retry fetch if the reset error boundary has been reset', async () => {
|
|
667
|
+
const consoleMock = vi
|
|
668
|
+
.spyOn(console, 'error')
|
|
669
|
+
.mockImplementation(() => undefined)
|
|
670
|
+
const key = queryKey()
|
|
671
|
+
|
|
672
|
+
let succeed = false
|
|
673
|
+
|
|
674
|
+
function Page() {
|
|
675
|
+
const [{ data }] = useQueries({
|
|
676
|
+
queries: [
|
|
677
|
+
{
|
|
678
|
+
queryKey: key,
|
|
679
|
+
queryFn: async () => {
|
|
680
|
+
await sleep(10)
|
|
681
|
+
if (!succeed) {
|
|
682
|
+
throw new Error('Error')
|
|
683
|
+
} else {
|
|
684
|
+
return 'data'
|
|
685
|
+
}
|
|
686
|
+
},
|
|
687
|
+
retry: false,
|
|
688
|
+
throwOnError: true,
|
|
689
|
+
retryOnMount: true,
|
|
690
|
+
},
|
|
691
|
+
],
|
|
692
|
+
})
|
|
693
|
+
return <div>{data}</div>
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
const rendered = renderWithClient(
|
|
697
|
+
queryClient,
|
|
698
|
+
<QueryErrorResetBoundary>
|
|
699
|
+
{({ reset }) => (
|
|
700
|
+
<ErrorBoundary
|
|
701
|
+
onReset={reset}
|
|
702
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
703
|
+
<div>
|
|
704
|
+
<div>error boundary</div>
|
|
705
|
+
<button
|
|
706
|
+
onClick={() => {
|
|
707
|
+
resetErrorBoundary()
|
|
708
|
+
}}
|
|
709
|
+
>
|
|
710
|
+
retry
|
|
711
|
+
</button>
|
|
712
|
+
</div>
|
|
713
|
+
)}
|
|
714
|
+
>
|
|
715
|
+
<Page />
|
|
716
|
+
</ErrorBoundary>
|
|
717
|
+
)}
|
|
718
|
+
</QueryErrorResetBoundary>,
|
|
719
|
+
)
|
|
603
720
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
.
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
721
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
722
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
723
|
+
succeed = true
|
|
724
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
725
|
+
await waitFor(() => rendered.getByText('data'))
|
|
726
|
+
consoleMock.mockRestore()
|
|
727
|
+
})
|
|
728
|
+
|
|
729
|
+
it('with suspense should retry fetch if the reset error boundary has been reset', async () => {
|
|
730
|
+
const key = queryKey()
|
|
731
|
+
const consoleMock = vi
|
|
732
|
+
.spyOn(console, 'error')
|
|
733
|
+
.mockImplementation(() => undefined)
|
|
734
|
+
|
|
735
|
+
let succeed = false
|
|
736
|
+
|
|
737
|
+
function Page() {
|
|
738
|
+
const [{ data }] = useQueries({
|
|
739
|
+
queries: [
|
|
740
|
+
{
|
|
741
|
+
queryKey: key,
|
|
742
|
+
queryFn: async () => {
|
|
743
|
+
await sleep(10)
|
|
744
|
+
if (!succeed) {
|
|
745
|
+
throw new Error('Error')
|
|
746
|
+
} else {
|
|
747
|
+
return 'data'
|
|
748
|
+
}
|
|
749
|
+
},
|
|
750
|
+
retry: false,
|
|
751
|
+
throwOnError: true,
|
|
752
|
+
retryOnMount: true,
|
|
753
|
+
suspense: true,
|
|
754
|
+
},
|
|
755
|
+
],
|
|
756
|
+
})
|
|
757
|
+
return <div>{data}</div>
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
const rendered = renderWithClient(
|
|
761
|
+
queryClient,
|
|
762
|
+
<QueryErrorResetBoundary>
|
|
763
|
+
{({ reset }) => (
|
|
764
|
+
<ErrorBoundary
|
|
765
|
+
onReset={reset}
|
|
766
|
+
fallbackRender={({ resetErrorBoundary }) => (
|
|
767
|
+
<div>
|
|
768
|
+
<div>error boundary</div>
|
|
769
|
+
<button
|
|
770
|
+
onClick={() => {
|
|
771
|
+
resetErrorBoundary()
|
|
772
|
+
}}
|
|
773
|
+
>
|
|
774
|
+
retry
|
|
775
|
+
</button>
|
|
776
|
+
</div>
|
|
777
|
+
)}
|
|
778
|
+
>
|
|
779
|
+
<React.Suspense fallback="Loader">
|
|
780
|
+
<Page />
|
|
781
|
+
</React.Suspense>
|
|
782
|
+
</ErrorBoundary>
|
|
783
|
+
)}
|
|
784
|
+
</QueryErrorResetBoundary>,
|
|
785
|
+
)
|
|
612
786
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
} else {
|
|
621
|
-
return 'data'
|
|
622
|
-
}
|
|
623
|
-
},
|
|
624
|
-
retry: false,
|
|
625
|
-
throwErrors: true,
|
|
626
|
-
})
|
|
627
|
-
return <div>{data}</div>
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
const rendered = renderWithClient(
|
|
631
|
-
queryClient,
|
|
632
|
-
<QueryErrorResetBoundary>
|
|
633
|
-
{({ reset }) => (
|
|
634
|
-
<ErrorBoundary
|
|
635
|
-
onReset={reset}
|
|
636
|
-
fallbackRender={({ resetErrorBoundary }) => (
|
|
637
|
-
<div>
|
|
638
|
-
<div>error boundary</div>
|
|
639
|
-
<button
|
|
640
|
-
onClick={() => {
|
|
641
|
-
resetErrorBoundary()
|
|
642
|
-
}}
|
|
643
|
-
>
|
|
644
|
-
retry
|
|
645
|
-
</button>
|
|
646
|
-
</div>
|
|
647
|
-
)}
|
|
648
|
-
>
|
|
649
|
-
<Page />
|
|
650
|
-
</ErrorBoundary>
|
|
651
|
-
)}
|
|
652
|
-
</QueryErrorResetBoundary>,
|
|
653
|
-
)
|
|
654
|
-
|
|
655
|
-
await waitFor(() => rendered.getByText('error boundary'))
|
|
656
|
-
await waitFor(() => rendered.getByText('retry'))
|
|
657
|
-
succeed = true
|
|
658
|
-
fireEvent.click(rendered.getByText('retry'))
|
|
659
|
-
await waitFor(() => rendered.getByText('data'))
|
|
660
|
-
consoleMock.mockRestore()
|
|
787
|
+
await waitFor(() => rendered.getByText('error boundary'))
|
|
788
|
+
await waitFor(() => rendered.getByText('retry'))
|
|
789
|
+
succeed = true
|
|
790
|
+
fireEvent.click(rendered.getByText('retry'))
|
|
791
|
+
await waitFor(() => rendered.getByText('data'))
|
|
792
|
+
consoleMock.mockRestore()
|
|
793
|
+
})
|
|
661
794
|
})
|
|
662
795
|
})
|