Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

queryClient.clear() breaks with suspense and when query goes from success to fail #2157

Closed
flybayer opened this issue Apr 20, 2021 · 2 comments
Labels

Comments

@flybayer
Copy link
Contributor

flybayer commented Apr 20, 2021

Describe the bug

Using queryClient.clear() with suspense enabled causes an infinite loop. We encountered this in Blitz on user logout: blitz-js/blitz#2249

To Reproduce

Add the following to src/react/tests/suspense.test.tsx

  it('should render error boundary when query goes from success to fail with clear()', async () => {
    const key = queryKey()

    let succeed = true
    const consoleMock = mockConsoleError()

    function Page() {
      useQuery(
        key,
        async () => {
          console.log('query')
          await sleep(10)
          if (!succeed) {
            throw new Error('Suspense Error Bingo')
          } else {
            return 'data'
          }
        },
        {
          retry: false,
          suspense: true,
        }
      )
      return <div>rendered</div>
    }

    function App() {
      const { reset } = useQueryErrorResetBoundary()
      return (
        <ErrorBoundary
          onReset={reset}
          fallbackRender={({ resetErrorBoundary }) => (
            <div>
              <div>error boundary</div>
              <button
                onClick={() => {
                  resetErrorBoundary()
                }}
              >
                retry
              </button>
            </div>
          )}
        >
          <React.Suspense fallback="Loading...">
            <Page />
          </React.Suspense>
        </ErrorBoundary>
      )
    }

    const rendered = renderWithClient(queryClient, <App />)

    await waitFor(() => rendered.getByText('Loading...'))
    await waitFor(() => rendered.getByText('rendered'))

    succeed = false
    queryClient.clear()
    await waitFor(() => rendered.getByText('error boundary'))
    consoleMock.mockRestore()
  })

Expected behavior

Should Work

Additional context

React-query 3.13.9

Workaround

-queryClient.clear()
+await queryClient.cancelQueries()
+await queryClient.resetQueries()
+queryClient.getMutationCache().clear()

@tannerlinsley @TkDodo

@TkDodo
Copy link
Collaborator

TkDodo commented Aug 12, 2021

@flybayer on the latest master, the provided test case times out with:

Error: Unable to find an element with the text: error boundary.

at

await waitFor(() => rendered.getByText('error boundary'))

and I think that's the correct behaviour. By just calling queryClient.clear, we'll remove all entries from the cache, but that doesn't inform active observers. So nothing re-renders the Page, so it doesn't refetch and also doesn't show the error boundary.

can you check if we maybe fixed the issue with the recent changes to shouldFetchOptionally, maybe this issue is obsolete now? Thanks

@TkDodo
Copy link
Collaborator

TkDodo commented Sep 3, 2022

closing as this is pretty stale and the provided test case doesn't behave as described anymore. Please reopen with a new reproduction if necessary.

@TkDodo TkDodo closed this as not planned Won't fix, can't repro, duplicate, stale Sep 3, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants