diff --git a/docs/src/pages/guides/testing.md b/docs/src/pages/guides/testing.md index f348358462..892fadf5b4 100644 --- a/docs/src/pages/guides/testing.md +++ b/docs/src/pages/guides/testing.md @@ -85,6 +85,10 @@ setLogger({ }) ``` +## Set cacheTime to Infinity with Jest + +`cacheTime` is set to 5 minutes by default. It means that the cache garbage collector timer will be triggered every 5 minutes. If you use Jest, you can set the `cacheTime` to `Infinity` to prevent "Jest did not exit one second after the test run completed" error message. + ## Testing Network Calls The primary use for React Query is to cache network requests, so it's important that we can test our code is making the correct network requests in the first place. diff --git a/src/react/tests/suspense.test.tsx b/src/react/tests/suspense.test.tsx index 1dd4704110..50a63e22d4 100644 --- a/src/react/tests/suspense.test.tsx +++ b/src/react/tests/suspense.test.tsx @@ -890,4 +890,49 @@ describe("useQuery's in Suspense mode", () => { await waitFor(() => rendered.getByText('error boundary')) consoleMock.mockRestore() }) + + it('should render the correct amount of times in Suspense mode when cacheTime is set to 0', async () => { + const key = queryKey() + let state: UseQueryResult | null = null + + let count = 0 + let renders = 0 + + function Page() { + renders++ + + state = useQuery( + key, + async () => { + count++ + await sleep(10) + return count + }, + { suspense: true, cacheTime: 0 } + ) + + return ( +
+ rendered +
+ ) + } + + const rendered = renderWithClient( + queryClient, + + + + ) + + await waitFor(() => + expect(state).toMatchObject({ + data: 1, + status: 'success', + }) + ) + + expect(renders).toBe(2) + expect(rendered.queryByText('rendered')).not.toBeNull() + }) }) diff --git a/src/react/useBaseQuery.ts b/src/react/useBaseQuery.ts index 6db43cb2a4..0736532baa 100644 --- a/src/react/useBaseQuery.ts +++ b/src/react/useBaseQuery.ts @@ -59,6 +59,12 @@ export function useBaseQuery< if (typeof defaultedOptions.staleTime !== 'number') { defaultedOptions.staleTime = 1000 } + + // Set cache time to 1 if the option has been set to 0 + // when using suspense to prevent infinite loop of fetches + if (defaultedOptions.cacheTime === 0) { + defaultedOptions.cacheTime = 1 + } } if (defaultedOptions.suspense || defaultedOptions.useErrorBoundary) {