Skip to content

Commit 16baba4

Browse files
committed
fix(useQuery): make sure that disabled queries in error state don't throw
because if they would, you would just go directly to the ErrorBoundary again
1 parent 3534621 commit 16baba4

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

src/react/tests/QueryResetErrorBoundary.test.tsx

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,137 @@ describe('QueryErrorResetBoundary', () => {
7373
consoleMock.mockRestore()
7474
})
7575

76+
it('should not throw error if query is disabled', async () => {
77+
const key = queryKey()
78+
79+
let succeed = false
80+
const consoleMock = mockConsoleError()
81+
82+
function Page() {
83+
const { data, status } = useQuery(
84+
key,
85+
async () => {
86+
await sleep(10)
87+
if (!succeed) {
88+
throw new Error('Error')
89+
} else {
90+
return 'data'
91+
}
92+
},
93+
{
94+
retry: false,
95+
enabled: !succeed,
96+
useErrorBoundary: true,
97+
}
98+
)
99+
return (
100+
<div>
101+
<div>status: {status}</div>
102+
<div>{data}</div>
103+
</div>
104+
)
105+
}
106+
107+
const rendered = renderWithClient(
108+
queryClient,
109+
<QueryErrorResetBoundary>
110+
{({ reset }) => (
111+
<ErrorBoundary
112+
onReset={reset}
113+
fallbackRender={({ resetErrorBoundary }) => (
114+
<div>
115+
<div>error boundary</div>
116+
<button
117+
onClick={() => {
118+
resetErrorBoundary()
119+
}}
120+
>
121+
retry
122+
</button>
123+
</div>
124+
)}
125+
>
126+
<Page />
127+
</ErrorBoundary>
128+
)}
129+
</QueryErrorResetBoundary>
130+
)
131+
132+
await waitFor(() => rendered.getByText('error boundary'))
133+
await waitFor(() => rendered.getByText('retry'))
134+
succeed = true
135+
fireEvent.click(rendered.getByText('retry'))
136+
await waitFor(() => rendered.getByText('status: error'))
137+
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 key = queryKey()
143+
144+
let succeed = false
145+
const consoleMock = mockConsoleError()
146+
147+
function Page() {
148+
const [enabled, setEnabled] = React.useState(false)
149+
const { data } = useQuery(
150+
key,
151+
async () => {
152+
await sleep(10)
153+
if (!succeed) {
154+
throw new Error('Error')
155+
} else {
156+
return 'data'
157+
}
158+
},
159+
{
160+
retry: false,
161+
enabled,
162+
useErrorBoundary: true,
163+
}
164+
)
165+
166+
React.useEffect(() => {
167+
setEnabled(true)
168+
}, [])
169+
170+
return <div>{data}</div>
171+
}
172+
173+
const rendered = renderWithClient(
174+
queryClient,
175+
<QueryErrorResetBoundary>
176+
{({ reset }) => (
177+
<ErrorBoundary
178+
onReset={reset}
179+
fallbackRender={({ resetErrorBoundary }) => (
180+
<div>
181+
<div>error boundary</div>
182+
<button
183+
onClick={() => {
184+
resetErrorBoundary()
185+
}}
186+
>
187+
retry
188+
</button>
189+
</div>
190+
)}
191+
>
192+
<Page />
193+
</ErrorBoundary>
194+
)}
195+
</QueryErrorResetBoundary>
196+
)
197+
198+
await waitFor(() => rendered.getByText('error boundary'))
199+
await waitFor(() => rendered.getByText('retry'))
200+
succeed = true
201+
fireEvent.click(rendered.getByText('retry'))
202+
await waitFor(() => rendered.getByText('data'))
203+
204+
consoleMock.mockRestore()
205+
})
206+
76207
it('should not retry fetch if the reset error boundary has not been reset', async () => {
77208
const key = queryKey()
78209

src/react/useBaseQuery.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ export function useBaseQuery<
131131
// Handle error boundary
132132
if (
133133
result.isError &&
134+
defaultedOptions.enabled !== false &&
134135
!result.isFetching &&
135136
shouldThrowError(
136137
defaultedOptions.suspense,

0 commit comments

Comments
 (0)