Skip to content

experimental_prefetchInRender does not work with useQueryErrorResetBoundary #9978

@Lukas-Kullmann

Description

@Lukas-Kullmann

Describe the bug

I think there is something something missing with how errors are reset when using useQuery().promise. Which leads to the error boundary only being reset on the second try.

The problem is that you would use useQuery().promise differently from useSuspenseQuery():

  • With useSuspenseQuery(), you would have your <Suspense> and <ErrorBoundary> somewhere up the component tree from useSuspenseQuery:
    const App = () => {
      const { reset } = useQueryErrorResetBoundary();
      return (
        <Suspense fallback={<span>Loading...</span>}>
          <ErrorBoundary 
            fallbackRender={({ resetErrorBoundary }) => <button type="button" onClick={resetErrorBoundary}>Retry</button>}
            onReset={reset}
          >
            <Page />
          </ErrorBoundary>
        </Suspense>
      );
    }
    
    const Page = () => {
      const { data } = useSuspenseQuery(/* ... */);
    
      // do something with the data
    }
  • With useQuery().promise, you have <Suspense> and <ErrorBoundary> in the same component as useQuery():
    const App = () => <Page />;
    
    const Page = () => {
      const promiseData = useQuery({ experimental_prefetchInRender: true, /* ... */ }).promise;
      const { reset } = useQueryErrorResetBoundary();
    
      return (
        <Suspense fallback={<span>Loading...</span>}>
          <ErrorBoundary 
            fallbackRender={({ resetErrorBoundary }) => <button type="button" onClick={resetErrorBoundary}>Retry</button>}
            onReset={reset}
          >
            <MySubComponent promiseData={promiseData} />
          </ErrorBoundary>
        </Suspense>
      );
    }
    
    const MySubComponent = ({ promiseData }) => {
      const data = React.use(promiseData);
    
      /* do something with the data */
    }

The problem is that the query will not be retried if you click the retry-button in the second example. I think the problem is that the current mechanism relys on the component that contains useQuery() (or useSuspenseQuery for that matter) to re-mount. Which of course does not happen in the second example.

Your minimal, reproducible example

https://codesandbox.io/p/sandbox/admiring-bas-xgdrjg

Steps to reproduce

  1. Open Codesandbox
  2. Wait for the requests to finish: Both show a retry button
  3. Click retry button in first line (useSuspenseQuery())
  4. Click retry button in second line (useQuery().promise

Expected behavior

Both retry button should work the same: When you click them, the query is retried.
This, however, does only work for the useSuspenseQuery option. Not the useQuery().promise.

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

  • OS: macOS
  • Browsers: any that I tried (Firefox, Safari, Edge)

Tanstack Query adapter

react-query

TanStack Query version

5.90.12

TypeScript version

No response

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions