Repository: tannerlinsley/react-query
Pull request #2993 (2021-11-20 07:36:25)

fix(useQuery): fix tracked queries and error boundaries

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/tanstack/react-query/J8VFqcVetMAhtLWqV7vXvi3g7BYh](https://vercel.com/tanstack/react-query/J8VFqcVetMAhtLWqV7vXvi3g7BYh)  
✅ Preview: *In Progress*


TkDodo: @babycourageous fyi
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/2993/builds/190220) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit e88631d0d317134364cd55a98605203fb1e6c9c3:

|Sandbox| Source |
|--|--|
|[tannerlinsley/react-query: basic](https://codesandbox.io/s/tannerlinsley-react-query-basic-65v4w)| Configuration |
|[tannerlinsley/react-query: basic-typescript](https://codesandbox.io/s/tannerlinsley-react-query-basic-typescript-ug8x4)| Configuration |

codecov[bot]: # [Codecov](https://codecov.io/gh/tannerlinsley/react-query/pull/2993?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley) Report
> Merging [#2993](https://codecov.io/gh/tannerlinsley/react-query/pull/2993?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley) (e88631d) into [master](https://codecov.io/gh/tannerlinsley/react-query/commit/c1ae82ba188fd5abda5e256cac070145e5941447?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley) (c1ae82b) will **increase** coverage by `0.00%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/tannerlinsley/react-query/pull/2993/graphs/tree.svg?width=650&height=150&src=pr&token=jqEbswkEDQ&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley)](https://codecov.io/gh/tannerlinsley/react-query/pull/2993?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley)

```diff
@@           Coverage Diff           @@
##           master    #2993   +/-   ##
=======================================
  Coverage   96.40%   96.41%           
=======================================
  Files          45       45           
  Lines        2227     2232    +5     
  Branches      637      639    +2     
=======================================
+ Hits         2147     2152    +5     
  Misses         77       77           
  Partials        3        3           
```


| [Impacted Files](https://codecov.io/gh/tannerlinsley/react-query/pull/2993?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley) | Coverage Δ | |
|---|---|---|
| [src/core/queryObserver.ts](https://codecov.io/gh/tannerlinsley/react-query/pull/2993/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL2NvcmUvcXVlcnlPYnNlcnZlci50cw==) | `100.00% <100.00%> (ø)` | |
| [src/react/useBaseQuery.ts](https://codecov.io/gh/tannerlinsley/react-query/pull/2993/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL3JlYWN0L3VzZUJhc2VRdWVyeS50cw==) | `100.00% <100.00%> (ø)` | |
| [src/core/mutation.ts](https://codecov.io/gh/tannerlinsley/react-query/pull/2993/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL2NvcmUvbXV0YXRpb24udHM=) | `100.00% <0.00%> (ø)` | |
| [src/core/mutationCache.ts](https://codecov.io/gh/tannerlinsley/react-query/pull/2993/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL2NvcmUvbXV0YXRpb25DYWNoZS50cw==) | `100.00% <0.00%> (ø)` | |
| [src/devtools/devtools.tsx](https://codecov.io/gh/tannerlinsley/react-query/pull/2993/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL2RldnRvb2xzL2RldnRvb2xzLnRzeA==) | `79.08% <0.00%> (+0.10%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/tannerlinsley/react-query/pull/2993?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/tannerlinsley/react-query/pull/2993?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley). Last update [c1ae82b...e88631d](https://codecov.io/gh/tannerlinsley/react-query/pull/2993?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley).


Patch:
diff --git a/src/core/queryObserver.ts b/src/core/queryObserver.ts
index f1ab5c8d2..aa36cfd2c 100644
--- a/src/core/queryObserver.ts
+++ b/src/core/queryObserver.ts
@@ -232,24 +232,38 @@ export class QueryObserver<
   }
 
   trackResult(
-    result: QueryObserverResult<TData, TError>
+    result: QueryObserverResult<TData, TError>,
+    defaultedOptions: QueryObserverOptions<
+      TQueryFnData,
+      TError,
+      TData,
+      TQueryData,
+      TQueryKey
+    >
   ): QueryObserverResult<TData, TError> {
     const trackedResult = {} as QueryObserverResult<TData, TError>
 
+    const trackProp = (key: keyof QueryObserverResult) => {
+      if (!this.trackedProps.includes(key)) {
+        this.trackedProps.push(key)
+      }
+    }
+
     Object.keys(result).forEach(key => {
       Object.defineProperty(trackedResult, key, {
         configurable: false,
         enumerable: true,
         get: () => {
-          const typedKey = key as keyof QueryObserverResult
-          if (!this.trackedProps.includes(typedKey)) {
-            this.trackedProps.push(typedKey)
-          }
-          return result[typedKey]
+          trackProp(key as keyof QueryObserverResult)
+          return result[key as keyof QueryObserverResult]
         },
       })
     })
 
+    if (defaultedOptions.useErrorBoundary || defaultedOptions.suspense) {
+      trackProp('error')
+    }
+
     return trackedResult
   }
 
diff --git a/src/react/useBaseQuery.ts b/src/react/useBaseQuery.ts
index 693944fc3..3adb64e05 100644
--- a/src/react/useBaseQuery.ts
+++ b/src/react/useBaseQuery.ts
@@ -144,7 +144,7 @@ export function useBaseQuery<
 
   // Handle result property usage tracking
   if (defaultedOptions.notifyOnChangeProps === 'tracked') {
-    result = observer.trackResult(result)
+    result = observer.trackResult(result, defaultedOptions)
   }
 
   return result


Test patch:
diff --git a/src/react/tests/QueryResetErrorBoundary.test.tsx b/src/react/tests/QueryResetErrorBoundary.test.tsx
index f73210d25..5fc1e366f 100644
--- a/src/react/tests/QueryResetErrorBoundary.test.tsx
+++ b/src/react/tests/QueryResetErrorBoundary.test.tsx
@@ -592,4 +592,64 @@ describe('QueryErrorResetBoundary', () => {
 
     expect(rendered.queryByText('page')).not.toBeNull()
   })
+
+  it('should show error boundary when using tracked queries even though we do not track the error field', async () => {
+    const key = queryKey()
+
+    let succeed = false
+    const consoleMock = mockConsoleError()
+
+    function Page() {
+      const { data } = useQuery(
+        key,
+        async () => {
+          await sleep(10)
+          if (!succeed) {
+            throw new Error('Error')
+          } else {
+            return 'data'
+          }
+        },
+        {
+          retry: false,
+          useErrorBoundary: true,
+          notifyOnChangeProps: 'tracked',
+        }
+      )
+      return <div>{data}</div>
+    }
+
+    const rendered = renderWithClient(
+      queryClient,
+      <QueryErrorResetBoundary>
+        {({ reset }) => (
+          <ErrorBoundary
+            onReset={reset}
+            fallbackRender={({ resetErrorBoundary }) => (
+              <div>
+                <div>error boundary</div>
+                <button
+                  onClick={() => {
+                    resetErrorBoundary()
+                  }}
+                >
+                  retry
+                </button>
+              </div>
+            )}
+          >
+            <Page />
+          </ErrorBoundary>
+        )}
+      </QueryErrorResetBoundary>
+    )
+
+    await waitFor(() => rendered.getByText('error boundary'))
+    await waitFor(() => rendered.getByText('retry'))
+    succeed = true
+    fireEvent.click(rendered.getByText('retry'))
+    await waitFor(() => rendered.getByText('data'))
+
+    consoleMock.mockRestore()
+  })
 })