Repository: tannerlinsley/react-query
Pull request #2119 (2021-04-13 20:41:26)

Fix useInfiniteQuery suspense bug
Closes: https://github.com/tannerlinsley/react-query/issues/2095

This fixes the useInfiniteQuery suspense bug where `options.behavior` was missing and so `infiniteQueryBehavior.onFetch` was not being called, resulting incorrect query `data`.


vercel[bot]: This pull request is being automatically deployed with Vercel ([learn more](https://vercel.link/github-learn-more)).  
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: [https://vercel.com/tannerlinsley/react-query/5SzhGReNige5doqxFbt5GoifSL4y](https://vercel.com/tannerlinsley/react-query/5SzhGReNige5doqxFbt5GoifSL4y)  
✅ Preview: *In Progress*


codesandbox[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/tannerlinsley/react-query/pr/2119/builds/119378) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit e1938d039892e2dc3ce3246c4d871a343b62d852:

|Sandbox| Source |
|--|--|
|[tannerlinsley/react-query: basic](https://codesandbox.io/s/tannerlinsleyreact-query-basic-x7des)| Configuration |
|[tannerlinsley/react-query: basic-typescript](https://codesandbox.io/s/tannerlinsleyreact-query-basic-typescript-2ynbe)| Configuration |


Patch:
diff --git a/docs/src/pages/reference/useQuery.md b/docs/src/pages/reference/useQuery.md
index 839b659f3..d0c8c4ac3 100644
--- a/docs/src/pages/reference/useQuery.md
+++ b/docs/src/pages/reference/useQuery.md
@@ -168,6 +168,9 @@ const result = useQuery({
   - Optional
   - Defaults to `true`
   - If set to `false`, structural sharing between query results will be disabled.
+- `useErrorBoundary: boolean`
+  - Defaults to the global query config's `useErrorBoundary` value, which is false
+  - Set this to true if you want errors to be thrown in the render phase and propagated to the nearest error boundary
 
 **Returns**
 
diff --git a/src/core/infiniteQueryObserver.ts b/src/core/infiniteQueryObserver.ts
index dd9169644..2dd199ba8 100644
--- a/src/core/infiniteQueryObserver.ts
+++ b/src/core/infiniteQueryObserver.ts
@@ -75,6 +75,21 @@ export class InfiniteQueryObserver<
     })
   }
 
+  getOptimisticResult(
+    options: InfiniteQueryObserverOptions<
+      TQueryFnData,
+      TError,
+      TData,
+      TQueryData
+    >
+  ): InfiniteQueryObserverResult<TData, TError> {
+    options.behavior = infiniteQueryBehavior()
+    return super.getOptimisticResult(options) as InfiniteQueryObserverResult<
+      TData,
+      TError
+    >
+  }
+
   fetchNextPage(
     options?: FetchNextPageOptions
   ): Promise<InfiniteQueryObserverResult<TData, TError>> {
diff --git a/src/hydration/react.tsx b/src/hydration/react.tsx
index b9a21e860..62fe2964f 100644
--- a/src/hydration/react.tsx
+++ b/src/hydration/react.tsx
@@ -1,6 +1,6 @@
 import React from 'react'
 
-import { useQueryClient } from '../react'
+import { useQueryClient } from 'react-query'
 import { hydrate, HydrateOptions } from './hydration'
 
 export function useHydrate(state: unknown, options?: HydrateOptions) {
diff --git a/tsconfig.json b/tsconfig.json
index da4415a41..cf0b28838 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -13,7 +13,10 @@
     "noUnusedParameters": true,
     "skipLibCheck": true,
     "strict": true,
-    "types": ["jest"]
+    "types": ["jest"],
+    "paths": {
+      "react-query": ["./src/index.ts"]
+    }
   },
   "include": ["./src"]
 }
diff --git a/tsconfig.types.json b/tsconfig.types.json
index 8474ccb0b..d09c81e05 100644
--- a/tsconfig.types.json
+++ b/tsconfig.types.json
@@ -4,7 +4,10 @@
     "declaration": true,
     "declarationDir": "./types",
     "emitDeclarationOnly": true,
-    "noEmit": false
+    "noEmit": false,
+    "paths": {
+      "react-query": ["./src/index.ts"]
+    }
   },
   "files": [
     "./src/index.ts",


Test patch:
diff --git a/src/react/tests/suspense.test.tsx b/src/react/tests/suspense.test.tsx
index a52af6602..30450332d 100644
--- a/src/react/tests/suspense.test.tsx
+++ b/src/react/tests/suspense.test.tsx
@@ -72,19 +72,20 @@ describe("useQuery's in Suspense mode", () => {
     const states: UseInfiniteQueryResult<number>[] = []
 
     function Page() {
+      const [multiplier, setMultiplier] = React.useState(1)
       const state = useInfiniteQuery(
-        key,
-        ({ pageParam = 0 }) => Number(pageParam),
+        `${key}_${multiplier}`,
+        ({ pageParam = 1 }) => Number(pageParam * multiplier),
         {
           suspense: true,
           getNextPageParam: lastPage => lastPage + 1,
         }
       )
       states.push(state)
-      return null
+      return <button onClick={() => setMultiplier(2)}>next</button>
     }
 
-    renderWithClient(
+    const rendered = renderWithClient(
       queryClient,
       <React.Suspense fallback="loading">
         <Page />
@@ -95,7 +96,16 @@ describe("useQuery's in Suspense mode", () => {
 
     expect(states.length).toBe(1)
     expect(states[0]).toMatchObject({
-      data: { pages: [0], pageParams: [undefined] },
+      data: { pages: [1], pageParams: [undefined] },
+      status: 'success',
+    })
+
+    fireEvent.click(rendered.getByText('next'))
+    await sleep(10)
+
+    expect(states.length).toBe(3)
+    expect(states[2]).toMatchObject({
+      data: { pages: [2], pageParams: [undefined] },
       status: 'success',
     })
   })