Repository: tannerlinsley/react-query
Pull request #2548 (2021-08-06 04:14:11)

Support the ability to provide a context
This adds support for passing in a context as other robust libraries (such as Redux) support: https://react-redux.js.org/api/provider#props.

This is important as right now React Query supports creating multiple `queryClient` instances but does not currently support the ability to specify which `queryClient` instance should be used with `useQueryClient`. In the case of nested `QueryClientProvider` instances in an application, the ability to specify which context (and thus which `QueryClientProvider` and `queryClient`)  should be used is critical. This adds such capability.

These changes should be 100% backwards compatible.

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/2MPL9S7UaragnEhqRvziPUQeh8jS](https://vercel.com/tannerlinsley/react-query/2MPL9S7UaragnEhqRvziPUQeh8jS)  
✅ 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/2548/builds/156969) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 059c72b608a9044f38890102e70e0a20031fe469:

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

TkDodo: What would be the use-case for needing multiple, nested QueryClientProviders where you do _not_ want to lookup the nearest one?
ngallows: The scenario I have been seeing is an app container that wants to provide some core data using React Query but wants to have no coupling to the apps that it renders that may or may not be using their own React Query for their own data. In that case, trying to access the core data will try to access the app’s React Query instead of the app container’s.

Assuming a single context for all React Query instances leads to this issue and is the reason robust libraries like Redux support the option to specify which context to use at the provider and at the consumer level.
TkDodo: I think the code changes look fine, I'd still want @tannerlinsley's opinion here. We'd also need some tests and updates to the docs please. Feel free to wait with that until Tanner gives his okay :)
blackarctic: Any updates here?
TkDodo: @tannerlinsley what do you think please? Is that a feature that should make it into the library?
blackarctic: To illustrate the need for this a bit more clearly here:

```jsx
<ContainerDataProvider> // <-- Provides container data using its own React Query provider
  ...
  <AppDataProvider> // <-- Provides app data using its own React Query provider
    ...
      <MyComponentDataProvider> // <-- Provides component data using its own React Query provider
        <MyComponent />
      </MyComponentDataProvider>
    ...
  </AppDataProvider>
  ...
</ContainerDataProvider>
```

Each "DataProvider" uses its own React Query provider for isolation and abstraction. Those that consume the data of these providers should not have to know what library they are using for data fetching and storage.

In this case, `MyComponent` needs to access `useQuery` from both  `MyComponentDataProvider` and `ContainerDataProvider`. Unless we can specify which context we wish to use for each `useQuery`, it will default to `MyComponentDataProvider` and fail.
tannerlinsley: I think this is a valid addition as long as:
- It is backwards compatible
- Doesn't require any code gymnastics to support it. The code looks simple enough on my first look-through, so let's hope it stays that way
- It gets documented extremely well as an optional and often unnecessary feature
- It gets tested well.
TkDodo: @blackarctic would you like to continue with the PR now that we have the approval from Tanner?
blackarctic: Yes. Sounds like we need:

- Update branch to latest
- Add accompanying tests
- Add accompanying documentation
blackarctic: @TkDodo PR should be ready for re-review
codecov[bot]: # [Codecov](https://codecov.io/gh/tannerlinsley/react-query/pull/2548?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley) Report
> Merging [#2548](https://codecov.io/gh/tannerlinsley/react-query/pull/2548?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley) (3f0670b) into [master](https://codecov.io/gh/tannerlinsley/react-query/commit/dc2df1066fb35593ab9f7b852ee250424f212737?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley) (dc2df10) will **decrease** coverage by `0.02%`.
> The diff coverage is `96.66%`.

[![Impacted file tree graph](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/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/2548?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    #2548      +/-   ##
==========================================
- Coverage   96.45%   96.43%   -0.03%     
==========================================
  Files          45       45              
  Lines        2257     2270      +13     
  Branches      641      652      +11     
==========================================
+ Hits         2177     2189      +12     
- Misses         77       78       +1     
  Partials        3        3              
```


| [Impacted Files](https://codecov.io/gh/tannerlinsley/react-query/pull/2548?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley) | Coverage Δ | |
|---|---|---|
| [src/core/hydration.ts](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL2NvcmUvaHlkcmF0aW9uLnRz) | `100.00% <ø> (ø)` | |
| [src/devtools/devtools.tsx](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL2RldnRvb2xzL2RldnRvb2xzLnRzeA==) | `78.68% <66.66%> (-0.41%)` | :arrow_down: |
| [src/core/utils.ts](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL2NvcmUvdXRpbHMudHM=) | `100.00% <100.00%> (ø)` | |
| [src/devtools/tests/utils.tsx](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL2RldnRvb2xzL3Rlc3RzL3V0aWxzLnRzeA==) | `95.00% <100.00%> (+0.26%)` | :arrow_up: |
| [src/react/Hydrate.tsx](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL3JlYWN0L0h5ZHJhdGUudHN4) | `100.00% <100.00%> (ø)` | |
| [src/react/QueryClientProvider.tsx](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL3JlYWN0L1F1ZXJ5Q2xpZW50UHJvdmlkZXIudHN4) | `100.00% <100.00%> (ø)` | |
| [src/react/tests/utils.tsx](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL3JlYWN0L3Rlc3RzL3V0aWxzLnRzeA==) | `97.22% <100.00%> (+0.07%)` | :arrow_up: |
| [src/react/useBaseQuery.ts](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/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/react/useIsFetching.ts](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL3JlYWN0L3VzZUlzRmV0Y2hpbmcudHM=) | `100.00% <100.00%> (ø)` | |
| [src/react/useIsMutating.ts](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley#diff-c3JjL3JlYWN0L3VzZUlzTXV0YXRpbmcudHM=) | `100.00% <100.00%> (ø)` | |
| ... and [2 more](https://codecov.io/gh/tannerlinsley/react-query/pull/2548/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/tannerlinsley/react-query/pull/2548?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/2548?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Tanner+Linsley). Last update [dc2df10...3f0670b](https://codecov.io/gh/tannerlinsley/react-query/pull/2548?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).

TkDodo: code looks good - there seems to be one test failing consistently.
blackarctic: Not seeing any failing tests but it looks like coverage dipped by `0.03%` in `src/devtools/devtools.tsx`. However, none of the uncovered lines of code were touched as part of this PR. Trying to get this PR in, though, so I added a test to test some of the untested code in the file to get the coverage up.
TkDodo: Thank you. I am thinking that maybe we should wait with the PR until v4 though. We are planning to change the api for `useQueries` to become an object, which would fit this use-case very well, because we could provide the `context` option at the very top, working for all queries:

```
useQueries({
  queries: [query1, query2, ..,. queryN],
  context: MyContext
})
```
blackarctic: > Thank you. I am thinking that maybe we should wait with the PR until v4 though. We are planning to change the api for `useQueries` to become an object, which would fit this use-case very well, because we could provide the `context` option at the very top, working for all queries:
> 
> ```
> useQueries({
>   queries: [query1, query2, ..,. queryN],
>   context: MyContext
> })
> ```

That would mean each query config (`query1, query2, ..,. queryN`) could not contain their own context? I would prefer to do that as a followup as that changes a good amount of types and implementation.
TkDodo: Judging from the current implementation, I was under the impression that it is a requirement that each query in useQueries uses the same context?
blackarctic: > Judging from the current implementation, I was under the impression that it is a requirement that each query in useQueries uses the same context?

Correct, but this now changes the types of these query objects so that they cannot include the `context` option. They are now a different type of query object than what is passed to `useQuery`. This also changes the implementation of `useQueries` since we can no longer blindly pass this different query object (without the `context`) to handlers of single queries because those might be handling the `context`. This will require us to re-add the `context` to each query object before passing it to any single query handlers.
TkDodo: > Correct, but this now changes the types of these query objects so that they cannot include the context option. They are now a different type of query object than what is passed to useQuery. 

I think that's fine - we can `Omit` the `context` on type level for `useQueries`.

> This also changes the implementation of useQueries since we can no longer blindly pass this different query object (without the context) to handlers of single queries because those might be handling the context. This will require us to re-add the context to each query object before passing it to any single query handlers.

yes, we would need to spread the `context` from the top level into each of the queries. Is that a problem?
blackarctic: > > Correct, but this now changes the types of these query objects so that they cannot include the context option. They are now a different type of query object than what is passed to useQuery.
> 
> I think that's fine - we can `Omit` the `context` on type level for `useQueries`.
> 
> > This also changes the implementation of useQueries since we can no longer blindly pass this different query object (without the context) to handlers of single queries because those might be handling the context. This will require us to re-add the context to each query object before passing it to any single query handlers.
> 
> yes, we would need to spread the `context` from the top level into each of the queries. Is that a problem?

Nope, not a problem. Just outlining the additional changes that will need to happen and the increased risk of issues in long-running PRs.
TkDodo: I've just merged the new useQueries api into the `alpha` branch. can you please base your PR on `alpha`, thank you :)
TkDodo: This looks very good, thank you 🙏 . It seems that the `useQueryClient` api docs do not mention the new context yet, could we add that there as well?

Also, I'm a bit worried that the name `context` might be confused with the `queryFunctionContext` that we already have - the object that is injected into the `queryFn`. Do you think it would be better to choose a different name?
blackarctic: > This looks very good, thank you 🙏 . It seems that the `useQueryClient` api docs do not mention the new context yet, could we add that there as well?
> 
> Also, I'm a bit worried that the name `context` might be confused with the `queryFunctionContext` that we already have - the object that is injected into the `queryFn`. Do you think it would be better to choose a different name?

Hmmm, I see your point. Well we could call it `reactContext`, `reactQueryContext`, `customReactQueryContext`, `customReactContext`, `customReactQueryContext`, `queryContext`, or `customQueryContext`? Any suggestions?
TkDodo: can you also add something to the [New Features](https://react-query-alpha.tanstack.com/guides/migrating-to-react-query-4#new-features-) section in the migrating to v4 doc please. I think it's good to let people know that way that we now have this feature 🚀 
bertho-zero: Is it possible to export the default context too? I have the same structure as https://github.com/tannerlinsley/react-query/pull/2548#issuecomment-915496288 but I don't necessarily need to pass the context option everywhere.

I would like to use the parent context if it exists, much like `contextSharing` but without using `window`, the idea is to do something like:

```js
function SubApp({}) {
  // const parentQueryClient = useQueryClient(); // Does not work because throws an error if tested in isolation
  const parentQueryClient = useContext(QueryClientContext);
  const queryClient = useMemo(() => (parentQueryClient || new QueryClient()), [parentQueryClient]);

  return (
    <QueryClientProvider client={queryClient}>
      {/* ... */}
    </QueryClientProvider>
  );
}
```

Or just an option that skips the error from `useQueryClient`.
TkDodo: @blackarctic we are nearing the release of v4. is there a chance we could get this in?
blackarctic: > Is it possible to export the default context or `getQueryClientContext` too? I have the same structure as [#2548 (comment)](https://github.com/tannerlinsley/react-query/pull/2548#issuecomment-915496288) but I don't necessarily need to pass the context option everywhere.
> 
> I would like to use the parent context if it exists, much like `contextSharing` but without using `window`, the idea is to do something like:
> 
> ```js
> function SubApp({}) {
>   // const parentQueryClient = useQueryClient(); // Does not work because throws an error if tested in isolation
>   const parentQueryClient = useContext(QueryClientContext);
>   const queryClient = useMemo(() => (parentQueryClient || new QueryClient()), [parentQueryClient]);
> 
>   return (
>     <QueryClientProvider client={queryClient}>
>       {/* ... */}
>     </QueryClientProvider>
>   );
> }
> ```
> 
> Or just an option that skips the error from `useQueryClient`.

Exported the `defaultContext` from `QueryClientProvider`. @TkDodo Is that ok with you?
blackarctic: > can you also add something to the [New Features](https://react-query-alpha.tanstack.com/guides/migrating-to-react-query-4#new-features-) section in the migrating to v4 doc please. I think it's good to let people know that way that we now have this feature 🚀

Done
blackarctic: > @blackarctic we are nearing the release of v4. is there a chance we could get this in?

Sorry for the delay. Should be good to re-review.
blackarctic: > @blackarctic we are nearing the release of v4. is there a chance we could get this in?

@TkDodo Sorry for the delay. Should be good to re-review.

Patch:
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 420d141d5..000000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-  "workbench.colorCustomizations": {
-    "titleBar.activeBackground": "#00da63", // change this color!
-    "titleBar.inactiveBackground": "#00da63", // change this color!
-    "titleBar.activeForeground": "#ffffff", // change this color!
-    "titleBar.inactiveForeground": "#ffffff" // change this color!
-  }
-}
diff --git a/docs/src/pages/devtools.md b/docs/src/pages/devtools.md
index 4b4f2642a..121b8f6ca 100644
--- a/docs/src/pages/devtools.md
+++ b/docs/src/pages/devtools.md
@@ -18,6 +18,7 @@ import { ReactQueryDevtools } from 'react-query/devtools'
 ```
 
 By default, React Query Devtools are only included in bundles when `process.env.NODE_ENV === 'development'`, so you don't need to worry about excluding them during a production build.
+
 ## Floating Mode
 
 Floating Mode will mount the devtools as a fixed, floating element in your app and provide a toggle in the corner of the screen to show and hide the devtools. This toggle state will be stored and remembered in localStorage across reloads.
@@ -50,6 +51,8 @@ function App() {
 - `position?: "top-left" | "top-right" | "bottom-left" | "bottom-right"`
   - Defaults to `bottom-left`
   - The position of the React Query logo to open and close the devtools panel
+- `context?: React.Context<QueryClient | undefined>`
+  - Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
 
 ## Embedded Mode
 
diff --git a/docs/src/pages/guides/migrating-to-react-query-4.md b/docs/src/pages/guides/migrating-to-react-query-4.md
index e106cba9c..049fd91b2 100644
--- a/docs/src/pages/guides/migrating-to-react-query-4.md
+++ b/docs/src/pages/guides/migrating-to-react-query-4.md
@@ -282,7 +282,7 @@ It was possible to change the logger globally by calling `setLogger`. In v4, tha
 + const queryClient = new QueryClient({ logger: customLogger })
 ```
 
-### Undefined is an illegale cache value for successful queries
+### Undefined is an illegal cache value for successful queries
 
 In order to make bailing out of updates possible by returning `undefined`, we had to make `undefined` an illegal cache value. This is in-line with other concepts of react-query, for example, returning `undefined` from the [initialData function](guides/initial-query-data#initial-data-function) will also _not_ set data.
 
@@ -301,6 +301,20 @@ This is now disallowed on type level; at runtime, `undefined` will be transforme
 
 As of v4, React Query is optimized for modern browsers. We have updated our browserslist to produce a more modern, performant and smaller bundle. You can read about the requirements [here](../installation#requirements).
 
+### The idle state has been removed
+
+With the introduction of the new [fetchStatus](../guides/queries#fetchstatus) for better offline support, the `idle` state became irrelevant, because `fetchStatus: 'idle'` captures the same state better. For more information, please read [Why two different states](../guides/queries#why-two-different-states).
+
+This will mostly affect `disabled` queries that don't have any `data` yet, as those were in `idle` state before:
+
+```diff
+- status: 'idle'
++ status: 'loading'
++ fetchStatus: 'idle'
+```
+
+Also, have a look at [the guide on dependent queries](../guides/dependent-queries)
+
 ## New Features 🚀
 
 ### Proper offline support
@@ -332,3 +346,90 @@ When using the [functional updater form of setQueryData](../reference/QueryClien
    (previousTodo) => previousTodo ? { ...previousTodo, done: true } : undefined
 )
  ```
+
+ ### Custom Contexts for Multiple Providers
+
+Custom contexts can now be specified to pair hooks with their matching `Provider`. This is critical when there may be multiple React Query `Provider` instances in the component tree and you need to ensure your hook uses the correct `Provider` instance.
+
+An example:
+
+1) Create a data package.
+
+```tsx
+// Our first data package: @my-scope/container-data
+
+const context = React.createContext<QueryClient | undefined>();
+const queryCache = new QueryCache()
+const queryClient = new QueryClient({ queryCache, context })
+
+
+export const useUser = () => {
+  return useQuery(USER_KEY, USER_FETCHER, {
+    context,
+  })
+}
+
+export const ContainerDataProvider: React.FC = ({ children }) => {
+  return (
+    <QueryClientProvider client={queryClient} context={context}>
+      {children}
+    </QueryClientProvider>
+  );
+}
+
+```
+
+2) Create a second data package.
+
+```tsx
+// Our second data package: @my-scope/my-component-data
+
+const context = React.createContext<QueryClient | undefined>();
+const queryCache = new QueryCache()
+const queryClient = new QueryClient({ queryCache, context })
+
+
+export const useItems = () => {
+  return useQuery(ITEMS_KEY, ITEMS_FETCHER, {
+    context,
+  })
+}
+
+export const MyComponentDataProvider: React.FC = ({ children }) => {
+  return (
+    <QueryClientProvider client={queryClient} context={context}>
+      {children}
+    </QueryClientProvider>
+  );
+}
+
+```
+
+3) Use these two data packages in your application.
+
+```tsx
+// Our application
+
+import { ContainerDataProvider, useUser } from "@my-scope/container-data";
+import { AppDataProvider } from "@my-scope/app-data";
+import { MyComponentDataProvider, useItems } from "@my-scope/my-component-data";
+
+<ContainerDataProvider> // <-- Provides container data (like "user") using its own React Query provider
+  ...
+  <AppDataProvider> // <-- Provides app data using its own React Query provider (unused in this example)
+    ...
+      <MyComponentDataProvider> // <-- Provides component data (like "items") using its own React Query provider
+        <MyComponent />
+      </MyComponentDataProvider>
+    ...
+  </AppDataProvider>
+  ...
+</ContainerDataProvider>
+
+// Example of hooks provided by the "DataProvider" components above:
+const MyComponent = () => {
+  const user = useUser(); // <-- Uses the context specified in ContainerDataProvider.
+  const items = useItems(); // <-- Uses the context specified in MyComponentDataProvider
+  ...
+}
+```
diff --git a/docs/src/pages/reference/QueryClientProvider.md b/docs/src/pages/reference/QueryClientProvider.md
index e31338de6..f9ea75ba6 100644
--- a/docs/src/pages/reference/QueryClientProvider.md
+++ b/docs/src/pages/reference/QueryClientProvider.md
@@ -14,6 +14,7 @@ function App() {
   return <QueryClientProvider client={queryClient}>...</QueryClientProvider>
 }
 ```
+
 **Options**
 
 - `client: QueryClient`
@@ -21,4 +22,6 @@ function App() {
   - the QueryClient instance to provide
 - `contextSharing: boolean`
   - defaults to `false`
-  - Set this to `true` to enable context sharing, which will share the first and at least one instance of the context across the window  to ensure that if React Query is used across  different bundles or microfrontends they will  all use the same **instance** of context, regardless of module scoping.
+  - Set this to `true` to enable context sharing, which will share the first and at least one instance of the context across the window to ensure that if React Query is used across different bundles or microfrontends they will all use the same **instance** of context, regardless of module scoping.
+- `context?: React.Context<QueryClient | undefined>`
+  - Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
diff --git a/docs/src/pages/reference/hydration.md b/docs/src/pages/reference/hydration.md
index a81543275..ce3899c93 100644
--- a/docs/src/pages/reference/hydration.md
+++ b/docs/src/pages/reference/hydration.md
@@ -84,6 +84,8 @@ hydrate(queryClient, dehydratedState, options)
     - Optional
     - `mutations: MutationOptions` The default mutation options to use for the hydrated mutations.
     - `queries: QueryOptions` The default query options to use for the hydrated queries.
+  - `context?: React.Context<QueryClient | undefined>`
+    - Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
 
 ### Limitations
 
@@ -108,6 +110,8 @@ useHydrate(dehydratedState, options)
   - Optional
   - `defaultOptions: QueryOptions`
     - The default query options to use for the hydrated queries.
+  - `context?: React.Context<QueryClient | undefined>`
+    - Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
 
 ## `Hydrate`
 
@@ -129,3 +133,5 @@ function App() {
   - Optional
   - `defaultOptions: QueryOptions`
     - The default query options to use for the hydrated queries.
+  - `context?: React.Context<QueryClient | undefined>`
+    - Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
diff --git a/docs/src/pages/reference/useIsFetching.md b/docs/src/pages/reference/useIsFetching.md
index 569c13344..fa0c793bd 100644
--- a/docs/src/pages/reference/useIsFetching.md
+++ b/docs/src/pages/reference/useIsFetching.md
@@ -17,6 +17,8 @@ const isFetchingPosts = useIsFetching(['posts'])
 
 - `queryKey?: QueryKey`: [Query Keys](../guides/query-keys)
 - `filters?: QueryFilters`: [Query Filters](../guides/filters#query-filters)
+- `context?: React.Context<QueryClient | undefined>`
+  - Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
 
 **Returns**
 
diff --git a/docs/src/pages/reference/useIsMutating.md b/docs/src/pages/reference/useIsMutating.md
index d9a6ad4cc..d75876f83 100644
--- a/docs/src/pages/reference/useIsMutating.md
+++ b/docs/src/pages/reference/useIsMutating.md
@@ -17,6 +17,8 @@ const isMutatingPosts = useIsMutating(['posts'])
 
 - `mutationKey?: string | unknown[]`
 - `filters?: MutationFilters`: [Mutation Filters](../guides/filters#mutation-filters)
+- `context?: React.Context<QueryClient | undefined>`
+  - Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
 
 **Returns**
 
diff --git a/docs/src/pages/reference/useMutation.md b/docs/src/pages/reference/useMutation.md
index cb3c611d7..70793e17a 100644
--- a/docs/src/pages/reference/useMutation.md
+++ b/docs/src/pages/reference/useMutation.md
@@ -87,6 +87,8 @@ mutate(variables, {
 - `meta: Record<string, unknown>`
   - Optional
   - If set, stores additional information on the mutation cache entry that can be used as needed. It will be accessible wherever the `mutation` is available (eg. `onError`, `onSuccess` functions of the `MutationCache`).
+- `context?: React.Context<QueryClient | undefined>`
+  - Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
 
 **Returns**
 
diff --git a/docs/src/pages/reference/useQueries.md b/docs/src/pages/reference/useQueries.md
index 0849033ef..bda41f3fa 100644
--- a/docs/src/pages/reference/useQueries.md
+++ b/docs/src/pages/reference/useQueries.md
@@ -16,7 +16,10 @@ const results = useQueries({
 
 **Options**
 
-The `useQueries` hook accepts an options object with a **queries** key whose value is an array with query option objects identical to the [`useQuery` hook](/reference/useQuery).
+The `useQueries` hook accepts an options object with a **queries** key whose value is an array with query option objects identical to the [`useQuery` hook](/reference/useQuery) (excluding the `context` option).
+
+- `context?: React.Context<QueryClient | undefined>`
+  - Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
 
 **Returns**
 
diff --git a/docs/src/pages/reference/useQuery.md b/docs/src/pages/reference/useQuery.md
index 8040e1a15..4045b3e0c 100644
--- a/docs/src/pages/reference/useQuery.md
+++ b/docs/src/pages/reference/useQuery.md
@@ -15,7 +15,6 @@ const {
   isFetchedAfterMount,
   isFetching,
   isPaused,
-  isIdle,
   isLoading,
   isLoadingError,
   isPlaceholderData,
@@ -185,6 +184,8 @@ const result = useQuery({
 - `meta: Record<string, unknown>`
   - Optional
   - If set, stores additional information on the query cache entry that can be used as needed. It will be accessible wherever the `query` is available, and is also part of the `QueryFunctionContext` provided to the `queryFn`.
+- `context?: React.Context<QueryClient | undefined>`
+  - Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
 
 **Returns**
 
diff --git a/src/core/hydration.ts b/src/core/hydration.ts
index c45dd86ab..830d64bb2 100644
--- a/src/core/hydration.ts
+++ b/src/core/hydration.ts
@@ -1,3 +1,4 @@
+import type { ContextOptions } from '../reactjs/types'
 import type { QueryClient } from './queryClient'
 import type { Query, QueryState } from './query'
 import type {
@@ -17,7 +18,7 @@ export interface DehydrateOptions {
   shouldDehydrateQuery?: ShouldDehydrateQueryFunction
 }
 
-export interface HydrateOptions {
+export interface HydrateOptions extends ContextOptions {
   defaultOptions?: {
     queries?: QueryOptions
     mutations?: MutationOptions
diff --git a/src/core/utils.ts b/src/core/utils.ts
index 0c4c9b0fc..14773db39 100644
--- a/src/core/utils.ts
+++ b/src/core/utils.ts
@@ -154,11 +154,17 @@ export function parseFilterArgs<
     : [arg1 || {}, arg2]) as [TFilters, TOptions]
 }
 
-export function parseMutationFilterArgs(
-  arg1?: QueryKey | MutationFilters,
-  arg2?: MutationFilters
-): MutationFilters | undefined {
-  return isQueryKey(arg1) ? { ...arg2, mutationKey: arg1 } : arg1
+export function parseMutationFilterArgs<
+  TFilters extends MutationFilters,
+  TOptions = unknown
+>(
+  arg1?: QueryKey | TFilters,
+  arg2?: TFilters | TOptions,
+  arg3?: TOptions
+): [TFilters, TOptions | undefined] {
+  return (isQueryKey(arg1)
+    ? [{ ...arg2, mutationKey: arg1 }, arg3]
+    : [arg1 || {}, arg2]) as [TFilters, TOptions]
 }
 
 export function matchQuery(
diff --git a/src/devtools/devtools.tsx b/src/devtools/devtools.tsx
index b102a46ca..fc632fae9 100644
--- a/src/devtools/devtools.tsx
+++ b/src/devtools/devtools.tsx
@@ -1,6 +1,11 @@
 import React from 'react'
 
-import { Query, useQueryClient, onlineManager } from 'react-query'
+import {
+  Query,
+  ContextOptions,
+  useQueryClient,
+  onlineManager,
+} from 'react-query'
 import { matchSorter } from 'match-sorter'
 import useLocalStorage from './useLocalStorage'
 import { useIsMounted, useSafeState } from './utils'
@@ -21,7 +26,7 @@ import Explorer from './Explorer'
 import Logo from './Logo'
 import { noop } from '../core/utils'
 
-interface DevtoolsOptions {
+interface DevtoolsOptions extends ContextOptions {
   /**
    * Set this true if you want the dev tools to default to being open
    */
@@ -60,7 +65,7 @@ interface DevtoolsOptions {
   containerElement?: string | any
 }
 
-interface DevtoolsPanelOptions {
+interface DevtoolsPanelOptions extends ContextOptions {
   /**
    * The standard React style object used to style a component with inline styles
    */
@@ -92,6 +97,7 @@ export function ReactQueryDevtools({
   toggleButtonProps = {},
   position = 'bottom-left',
   containerElement: Container = 'aside',
+  context,
 }: DevtoolsOptions): React.ReactElement | null {
   const rootRef = React.useRef<HTMLDivElement>(null)
   const panelRef = React.useRef<HTMLDivElement>(null)
@@ -229,6 +235,7 @@ export function ReactQueryDevtools({
       <ThemeProvider theme={theme}>
         <ReactQueryDevtoolsPanel
           ref={panelRef as any}
+          context={context}
           {...otherPanelProps}
           style={{
             position: 'fixed',
@@ -381,9 +388,15 @@ export const ReactQueryDevtoolsPanel = React.forwardRef<
   HTMLDivElement,
   DevtoolsPanelOptions
 >(function ReactQueryDevtoolsPanel(props, ref): React.ReactElement {
-  const { isOpen = true, setIsOpen, handleDragStart, ...panelProps } = props
-
-  const queryClient = useQueryClient()
+  const {
+    isOpen = true,
+    setIsOpen,
+    handleDragStart,
+    context,
+    ...panelProps
+  } = props
+
+  const queryClient = useQueryClient({ context })
   const queryCache = queryClient.getQueryCache()
 
   const [sort, setSort] = useLocalStorage(
diff --git a/src/reactjs/Hydrate.tsx b/src/reactjs/Hydrate.tsx
index 522189740..d5b172e51 100644
--- a/src/reactjs/Hydrate.tsx
+++ b/src/reactjs/Hydrate.tsx
@@ -3,8 +3,8 @@ import React from 'react'
 import { hydrate, HydrateOptions } from '../core'
 import { useQueryClient } from './QueryClientProvider'
 
-export function useHydrate(state: unknown, options?: HydrateOptions) {
-  const queryClient = useQueryClient()
+export function useHydrate(state: unknown, options: HydrateOptions = {}) {
+  const queryClient = useQueryClient({ context: options.context })
 
   const optionsRef = React.useRef(options)
   optionsRef.current = options
diff --git a/src/reactjs/QueryClientProvider.tsx b/src/reactjs/QueryClientProvider.tsx
index e0ea8baa5..f5d52c178 100644
--- a/src/reactjs/QueryClientProvider.tsx
+++ b/src/reactjs/QueryClientProvider.tsx
@@ -1,6 +1,7 @@
 import React from 'react'
 
 import { QueryClient } from '../core'
+import { ContextOptions } from '../reactjs/types'
 
 declare global {
   interface Window {
@@ -8,16 +9,25 @@ declare global {
   }
 }
 
-const defaultContext = React.createContext<QueryClient | undefined>(undefined)
+export const defaultContext = React.createContext<QueryClient | undefined>(
+  undefined
+)
 const QueryClientSharingContext = React.createContext<boolean>(false)
 
-// if contextSharing is on, we share the first and at least one
+// If we are given a context, we will use it.
+// Otherwise, if contextSharing is on, we share the first and at least one
 // instance of the context across the window
 // to ensure that if React Query is used across
 // different bundles or microfrontends they will
 // all use the same **instance** of context, regardless
 // of module scoping.
-function getQueryClientContext(contextSharing: boolean) {
+function getQueryClientContext(
+  context: React.Context<QueryClient | undefined> | undefined,
+  contextSharing: boolean
+) {
+  if (context) {
+    return context
+  }
   if (contextSharing && typeof window !== 'undefined') {
     if (!window.ReactQueryClientContext) {
       window.ReactQueryClientContext = defaultContext
@@ -29,9 +39,9 @@ function getQueryClientContext(contextSharing: boolean) {
   return defaultContext
 }
 
-export const useQueryClient = () => {
+export const useQueryClient = ({ context }: ContextOptions = {}) => {
   const queryClient = React.useContext(
-    getQueryClientContext(React.useContext(QueryClientSharingContext))
+    getQueryClientContext(context, React.useContext(QueryClientSharingContext))
   )
 
   if (!queryClient) {
@@ -41,15 +51,26 @@ export const useQueryClient = () => {
   return queryClient
 }
 
-export interface QueryClientProviderProps {
+type QueryClientProviderPropsBase = {
   client: QueryClient
-  contextSharing?: boolean
 }
+type QueryClientProviderPropsWithContext = ContextOptions & {
+  contextSharing?: never
+} & QueryClientProviderPropsBase
+type QueryClientProviderPropsWithContextSharing = {
+  context?: never
+  contextSharing?: boolean
+} & QueryClientProviderPropsBase
+
+export type QueryClientProviderProps =
+  | QueryClientProviderPropsWithContext
+  | QueryClientProviderPropsWithContextSharing
 
 export const QueryClientProvider: React.FC<QueryClientProviderProps> = ({
   client,
-  contextSharing = false,
   children,
+  context,
+  contextSharing = false,
 }) => {
   React.useEffect(() => {
     client.mount()
@@ -58,10 +79,10 @@ export const QueryClientProvider: React.FC<QueryClientProviderProps> = ({
     }
   }, [client])
 
-  const Context = getQueryClientContext(contextSharing)
+  const Context = getQueryClientContext(context, contextSharing)
 
   return (
-    <QueryClientSharingContext.Provider value={contextSharing}>
+    <QueryClientSharingContext.Provider value={!context && contextSharing}>
       <Context.Provider value={client}>{children}</Context.Provider>
     </QueryClientSharingContext.Provider>
   )
diff --git a/src/reactjs/index.ts b/src/reactjs/index.ts
index b428b5fe8..1a678571a 100644
--- a/src/reactjs/index.ts
+++ b/src/reactjs/index.ts
@@ -1,7 +1,11 @@
 // Side effects
 import './setBatchUpdatesFn'
 
-export { QueryClientProvider, useQueryClient } from './QueryClientProvider'
+export {
+  defaultContext,
+  QueryClientProvider,
+  useQueryClient,
+} from './QueryClientProvider'
 export {
   QueryErrorResetBoundary,
   useQueryErrorResetBoundary,
diff --git a/src/reactjs/types.ts b/src/reactjs/types.ts
index 13ac8c451..5bf97177b 100644
--- a/src/reactjs/types.ts
+++ b/src/reactjs/types.ts
@@ -8,6 +8,14 @@ import {
   MutationObserverOptions,
   MutateFunction,
 } from '../core/types'
+import type { QueryClient } from '../core/queryClient'
+
+export interface ContextOptions {
+  /**
+   * Use this to pass your React Query context. Otherwise, `defaultContext` will be used.
+   */
+  context?: React.Context<QueryClient | undefined>
+}
 
 export interface UseBaseQueryOptions<
   TQueryFnData = unknown,
@@ -15,13 +23,8 @@ export interface UseBaseQueryOptions<
   TData = TQueryFnData,
   TQueryData = TQueryFnData,
   TQueryKey extends QueryKey = QueryKey
-> extends QueryObserverOptions<
-    TQueryFnData,
-    TError,
-    TData,
-    TQueryData,
-    TQueryKey
-  > {}
+> extends ContextOptions,
+    QueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey> {}
 
 export interface UseQueryOptions<
   TQueryFnData = unknown,
@@ -42,13 +45,14 @@ export interface UseInfiniteQueryOptions<
   TData = TQueryFnData,
   TQueryData = TQueryFnData,
   TQueryKey extends QueryKey = QueryKey
-> extends InfiniteQueryObserverOptions<
-    TQueryFnData,
-    TError,
-    TData,
-    TQueryData,
-    TQueryKey
-  > {}
+> extends ContextOptions,
+    InfiniteQueryObserverOptions<
+      TQueryFnData,
+      TError,
+      TData,
+      TQueryData,
+      TQueryKey
+    > {}
 
 export type UseBaseQueryResult<
   TData = unknown,
@@ -70,10 +74,11 @@ export interface UseMutationOptions<
   TError = unknown,
   TVariables = void,
   TContext = unknown
-> extends Omit<
-    MutationObserverOptions<TData, TError, TVariables, TContext>,
-    '_defaulted' | 'variables'
-  > {}
+> extends ContextOptions,
+    Omit<
+      MutationObserverOptions<TData, TError, TVariables, TContext>,
+      '_defaulted' | 'variables'
+    > {}
 
 export type UseMutateFunction<
   TData = unknown,
diff --git a/src/reactjs/useBaseQuery.ts b/src/reactjs/useBaseQuery.ts
index 9a11ce89a..3378661cd 100644
--- a/src/reactjs/useBaseQuery.ts
+++ b/src/reactjs/useBaseQuery.ts
@@ -27,7 +27,7 @@ export function useBaseQuery<
   const mountedRef = React.useRef(false)
   const [, forceUpdate] = React.useState(0)
 
-  const queryClient = useQueryClient()
+  const queryClient = useQueryClient({ context: options.context })
   const errorResetBoundary = useQueryErrorResetBoundary()
   const defaultedOptions = queryClient.defaultQueryOptions(options)
 
diff --git a/src/reactjs/useIsFetching.ts b/src/reactjs/useIsFetching.ts
index a1319c53d..8552881e1 100644
--- a/src/reactjs/useIsFetching.ts
+++ b/src/reactjs/useIsFetching.ts
@@ -2,23 +2,29 @@ import React from 'react'
 
 import { notifyManager } from '../core/notifyManager'
 import { QueryKey } from '../core/types'
+import { ContextOptions } from '../reactjs/types'
 import { parseFilterArgs, QueryFilters } from '../core/utils'
 import { useQueryClient } from './QueryClientProvider'
 
-export function useIsFetching(filters?: QueryFilters): number
+interface Options extends ContextOptions {}
+
+export function useIsFetching(filters?: QueryFilters, options?: Options): number
 export function useIsFetching(
   queryKey?: QueryKey,
-  filters?: QueryFilters
+  filters?: QueryFilters,
+  options?: Options
 ): number
 export function useIsFetching(
   arg1?: QueryKey | QueryFilters,
-  arg2?: QueryFilters
+  arg2?: QueryFilters | Options,
+  arg3?: Options
 ): number {
   const mountedRef = React.useRef(false)
 
-  const queryClient = useQueryClient()
+  const [filters, options = {}] = parseFilterArgs(arg1, arg2, arg3)
+
+  const queryClient = useQueryClient({ context: options.context })
 
-  const [filters] = parseFilterArgs(arg1, arg2)
   const [isFetching, setIsFetching] = React.useState(
     queryClient.isFetching(filters)
   )
diff --git a/src/reactjs/useIsMutating.ts b/src/reactjs/useIsMutating.ts
index b3baaec00..013525ba2 100644
--- a/src/reactjs/useIsMutating.ts
+++ b/src/reactjs/useIsMutating.ts
@@ -2,22 +2,30 @@ import React from 'react'
 
 import { notifyManager } from '../core/notifyManager'
 import { MutationKey } from '../core/types'
+import { ContextOptions } from '../reactjs/types'
 import { MutationFilters, parseMutationFilterArgs } from '../core/utils'
 import { useQueryClient } from './QueryClientProvider'
 
-export function useIsMutating(filters?: MutationFilters): number
+interface Options extends ContextOptions {}
+
+export function useIsMutating(
+  filters?: MutationFilters,
+  options?: Options
+): number
 export function useIsMutating(
   mutationKey?: MutationKey,
-  filters?: Omit<MutationFilters, 'mutationKey'>
+  filters?: Omit<MutationFilters, 'mutationKey'>,
+  options?: Options
 ): number
 export function useIsMutating(
   arg1?: MutationKey | MutationFilters,
-  arg2?: Omit<MutationFilters, 'mutationKey'>
+  arg2?: Omit<MutationFilters, 'mutationKey'> | Options,
+  arg3?: Options
 ): number {
   const mountedRef = React.useRef(false)
-  const filters = parseMutationFilterArgs(arg1, arg2)
+  const [filters, options = {}] = parseMutationFilterArgs(arg1, arg2, arg3)
 
-  const queryClient = useQueryClient()
+  const queryClient = useQueryClient({ context: options.context })
 
   const [isMutating, setIsMutating] = React.useState(
     queryClient.isMutating(filters)
diff --git a/src/reactjs/useMutation.ts b/src/reactjs/useMutation.ts
index 63a13ef40..71c0744d4 100644
--- a/src/reactjs/useMutation.ts
+++ b/src/reactjs/useMutation.ts
@@ -78,7 +78,7 @@ export function useMutation<
   const [, forceUpdate] = React.useState(0)
 
   const options = parseMutationArgs(arg1, arg2, arg3)
-  const queryClient = useQueryClient()
+  const queryClient = useQueryClient({ context: options.context })
 
   const obsRef = React.useRef<
     MutationObserver<TData, TError, TVariables, TContext>
diff --git a/src/reactjs/useQueries.ts b/src/reactjs/useQueries.ts
index f25c2511b..ab3005079 100644
--- a/src/reactjs/useQueries.ts
+++ b/src/reactjs/useQueries.ts
@@ -1,11 +1,20 @@
 import React from 'react'
-import { QueryFunction } from '../core/types'
+import { QueryKey, QueryFunction } from '../core/types'
 
 import { notifyManager } from '../core/notifyManager'
 import { QueriesObserver } from '../core/queriesObserver'
 import { useQueryClient } from './QueryClientProvider'
 import { UseQueryOptions, UseQueryResult } from './types'
 
+// This defines the `UseQueryOptions` that are accepted in `QueriesOptions` & `GetOptions`.
+// - `context` is omitted as it is passed as a root-level option to `useQueries` instead.
+type UseQueryOptionsForUseQueries<
+  TQueryFnData = unknown,
+  TError = unknown,
+  TData = TQueryFnData,
+  TQueryKey extends QueryKey = QueryKey
+> = Omit<UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>, 'context'>
+
 // Avoid TS depth-limit error in case of large array literal
 type MAXIMUM_DEPTH = 20
 
@@ -16,28 +25,33 @@ type GetOptions<T> =
     error?: infer TError
     data: infer TData
   }
-    ? UseQueryOptions<TQueryFnData, TError, TData>
+    ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>
     : T extends { queryFnData: infer TQueryFnData; error?: infer TError }
-    ? UseQueryOptions<TQueryFnData, TError>
+    ? UseQueryOptionsForUseQueries<TQueryFnData, TError>
     : T extends { data: infer TData; error?: infer TError }
-    ? UseQueryOptions<unknown, TError, TData>
+    ? UseQueryOptionsForUseQueries<unknown, TError, TData>
     : // Part 2: responsible for applying explicit type parameter to function arguments, if tuple [TQueryFnData, TError, TData]
     T extends [infer TQueryFnData, infer TError, infer TData]
-    ? UseQueryOptions<TQueryFnData, TError, TData>
+    ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData>
     : T extends [infer TQueryFnData, infer TError]
-    ? UseQueryOptions<TQueryFnData, TError>
+    ? UseQueryOptionsForUseQueries<TQueryFnData, TError>
     : T extends [infer TQueryFnData]
-    ? UseQueryOptions<TQueryFnData>
+    ? UseQueryOptionsForUseQueries<TQueryFnData>
     : // Part 3: responsible for inferring and enforcing type if no explicit parameter was provided
     T extends {
         queryFn?: QueryFunction<infer TQueryFnData, infer TQueryKey>
         select: (data: any) => infer TData
       }
-    ? UseQueryOptions<TQueryFnData, unknown, TData, TQueryKey>
+    ? UseQueryOptionsForUseQueries<TQueryFnData, unknown, TData, TQueryKey>
     : T extends { queryFn?: QueryFunction<infer TQueryFnData, infer TQueryKey> }
-    ? UseQueryOptions<TQueryFnData, unknown, TQueryFnData, TQueryKey>
+    ? UseQueryOptionsForUseQueries<
+        TQueryFnData,
+        unknown,
+        TQueryFnData,
+        TQueryKey
+      >
     : // Fallback
-      UseQueryOptions
+      UseQueryOptionsForUseQueries
 
 type GetResults<T> =
   // Part 1: responsible for mapping explicit type parameter to function result, if object
@@ -73,7 +87,7 @@ export type QueriesOptions<
   Result extends any[] = [],
   Depth extends ReadonlyArray<number> = []
 > = Depth['length'] extends MAXIMUM_DEPTH
-  ? UseQueryOptions[]
+  ? UseQueryOptionsForUseQueries[]
   : T extends []
   ? []
   : T extends [infer Head]
@@ -84,15 +98,15 @@ export type QueriesOptions<
   ? T
   : // If T is *some* array but we couldn't assign unknown[] to it, then it must hold some known/homogenous type!
   // use this to infer the param types in the case of Array.map() argument
-  T extends UseQueryOptions<
+  T extends UseQueryOptionsForUseQueries<
       infer TQueryFnData,
       infer TError,
       infer TData,
       infer TQueryKey
     >[]
-  ? UseQueryOptions<TQueryFnData, TError, TData, TQueryKey>[]
+  ? UseQueryOptionsForUseQueries<TQueryFnData, TError, TData, TQueryKey>[]
   : // Fallback
-    UseQueryOptions[]
+    UseQueryOptionsForUseQueries[]
 
 /**
  * QueriesResults reducer recursively maps type param to results
@@ -109,7 +123,7 @@ export type QueriesResults<
   ? [...Result, GetResults<Head>]
   : T extends [infer Head, ...infer Tail]
   ? QueriesResults<[...Tail], [...Result, GetResults<Head>], [...Depth, 1]>
-  : T extends UseQueryOptions<
+  : T extends UseQueryOptionsForUseQueries<
       infer TQueryFnData,
       infer TError,
       infer TData,
@@ -122,13 +136,15 @@ export type QueriesResults<
 
 export function useQueries<T extends any[]>({
   queries,
+  context,
 }: {
   queries: readonly [...QueriesOptions<T>]
+  context?: UseQueryOptions['context']
 }): QueriesResults<T> {
   const mountedRef = React.useRef(false)
   const [, forceUpdate] = React.useState(0)
 
-  const queryClient = useQueryClient()
+  const queryClient = useQueryClient({ context })
 
   const defaultedQueries = React.useMemo(
     () =>


Test patch:
diff --git a/src/devtools/tests/devtools.test.tsx b/src/devtools/tests/devtools.test.tsx
index 3ffe6e16d..30f2ac526 100644
--- a/src/devtools/tests/devtools.test.tsx
+++ b/src/devtools/tests/devtools.test.tsx
@@ -1,4 +1,5 @@
 import React from 'react'
+import { ErrorBoundary } from 'react-error-boundary'
 import {
   fireEvent,
   screen,
@@ -7,7 +8,7 @@ import {
   waitForElementToBeRemoved,
 } from '@testing-library/react'
 import '@testing-library/jest-dom'
-import { useQuery } from '../..'
+import { useQuery, QueryClient } from '../..'
 import {
   getByTextContent,
   renderWithClient,
@@ -77,6 +78,39 @@ describe('ReactQueryDevtools', () => {
     expect(onCloseClick).toHaveBeenCalledTimes(1)
   })
 
+  it('should be able to drag devtools without error', async () => {
+    const { queryClient } = createQueryClient()
+
+    function Page() {
+      const { data = 'default' } = useQuery(['check'], async () => {
+        await sleep(10)
+        return 'test'
+      })
+
+      return (
+        <div>
+          <h1>{data}</h1>
+        </div>
+      )
+    }
+
+    const result = renderWithClient(queryClient, <Page />, {
+      initialIsOpen: false,
+    })
+
+    const draggableElement = result.container
+      .querySelector('#ReactQueryDevtoolsPanel')
+      ?.querySelector('div')
+
+    if (!draggableElement) {
+      throw new Error('Could not find the draggable element')
+    }
+
+    await act(async () => {
+      fireEvent.mouseDown(draggableElement)
+    })
+  })
+
   it('should display the correct query states', async () => {
     const { queryClient, queryCache } = createQueryClient()
 
@@ -470,4 +504,100 @@ describe('ReactQueryDevtools', () => {
     expect(queries[1]?.textContent).toEqual(query2Hash)
     expect(queries[2]?.textContent).toEqual(query3Hash)
   })
+
+  describe('with custom context', () => {
+    it('should render without error when the custom context aligns', async () => {
+      const context = React.createContext<QueryClient | undefined>(undefined)
+      const { queryClient } = createQueryClient()
+
+      function Page() {
+        const { data = 'default' } = useQuery(['check'], async () => 'test', {
+          context,
+        })
+
+        return (
+          <div>
+            <h1>{data}</h1>
+          </div>
+        )
+      }
+
+      renderWithClient(queryClient, <Page />, {
+        initialIsOpen: false,
+        context,
+      })
+
+      await screen.findByRole('button', { name: /open react query devtools/i })
+    })
+
+    it('should render with error when the custom context is not passed to useQuery', async () => {
+      const consoleErrorMock = jest.spyOn(console, 'error')
+      consoleErrorMock.mockImplementation(() => undefined)
+
+      const context = React.createContext<QueryClient | undefined>(undefined)
+      const { queryClient } = createQueryClient()
+
+      function Page() {
+        const { data = 'default' } = useQuery(['check'], async () => 'test', {
+          useErrorBoundary: true,
+        })
+
+        return (
+          <div>
+            <h1>{data}</h1>
+          </div>
+        )
+      }
+
+      const rendered = renderWithClient(
+        queryClient,
+        <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>
+          <Page />
+        </ErrorBoundary>,
+        {
+          initialIsOpen: false,
+          context,
+        }
+      )
+
+      await waitFor(() => rendered.getByText('error boundary'))
+
+      consoleErrorMock.mockRestore()
+    })
+
+    it('should render with error when the custom context is not passed to ReactQueryDevtools', async () => {
+      const consoleErrorMock = jest.spyOn(console, 'error')
+      consoleErrorMock.mockImplementation(() => undefined)
+
+      const context = React.createContext<QueryClient | undefined>(undefined)
+      const { queryClient } = createQueryClient()
+
+      function Page() {
+        const { data = 'default' } = useQuery(['check'], async () => 'test', {
+          useErrorBoundary: true,
+          context,
+        })
+
+        return (
+          <div>
+            <h1>{data}</h1>
+          </div>
+        )
+      }
+
+      const rendered = renderWithClient(
+        queryClient,
+        <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>
+          <Page />
+        </ErrorBoundary>,
+        {
+          initialIsOpen: false,
+        }
+      )
+
+      await waitFor(() => rendered.getByText('error boundary'))
+
+      consoleErrorMock.mockRestore()
+    })
+  })
 })
diff --git a/src/devtools/tests/utils.tsx b/src/devtools/tests/utils.tsx
index d0d2afebd..0c0a36b16 100644
--- a/src/devtools/tests/utils.tsx
+++ b/src/devtools/tests/utils.tsx
@@ -7,10 +7,10 @@ import { QueryClient, QueryClientProvider, QueryCache } from '../..'
 export function renderWithClient(
   client: QueryClient,
   ui: React.ReactElement,
-  devtoolsOptions?: Parameters<typeof ReactQueryDevtools>[number]
+  devtoolsOptions: Parameters<typeof ReactQueryDevtools>[number] = {}
 ) {
   const { rerender, ...result } = render(
-    <QueryClientProvider client={client}>
+    <QueryClientProvider client={client} context={devtoolsOptions.context}>
       <ReactQueryDevtools {...devtoolsOptions} />
       {ui}
     </QueryClientProvider>
@@ -19,7 +19,7 @@ export function renderWithClient(
     ...result,
     rerender: (rerenderUi: React.ReactElement) =>
       rerender(
-        <QueryClientProvider client={client}>
+        <QueryClientProvider client={client} context={devtoolsOptions.context}>
           <ReactQueryDevtools {...devtoolsOptions} />
           {rerenderUi}
         </QueryClientProvider>
diff --git a/src/reactjs/tests/Hydrate.test.tsx b/src/reactjs/tests/Hydrate.test.tsx
index c3a827848..1bfd2d0c9 100644
--- a/src/reactjs/tests/Hydrate.test.tsx
+++ b/src/reactjs/tests/Hydrate.test.tsx
@@ -2,6 +2,7 @@ import React from 'react'
 import { render } from '@testing-library/react'
 
 import {
+  QueryClient,
   QueryClientProvider,
   QueryCache,
   useQuery,
@@ -21,7 +22,9 @@ describe('React hydration', () => {
   beforeAll(async () => {
     const queryCache = new QueryCache()
     const queryClient = createQueryClient({ queryCache })
-    await queryClient.prefetchQuery(['string'], () => dataQuery(['string']))
+    await queryClient.prefetchQuery(['string'], () =>
+      dataQuery(['stringCached'])
+    )
     const dehydrated = dehydrate(queryClient)
     stringifiedState = JSON.stringify(dehydrated)
     queryClient.clear()
@@ -49,10 +52,50 @@ describe('React hydration', () => {
         </QueryClientProvider>
       )
 
+      rendered.getByText('stringCached')
       await sleep(10)
       rendered.getByText('string')
       queryClient.clear()
     })
+
+    test('should hydrate queries to the cache on custom context', async () => {
+      const context = React.createContext<QueryClient | undefined>(undefined)
+
+      const queryCacheOuter = new QueryCache()
+      const queryCacheInner = new QueryCache()
+
+      const queryClientInner = new QueryClient({ queryCache: queryCacheInner })
+      const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter })
+
+      const dehydratedState = JSON.parse(stringifiedState)
+
+      function Page() {
+        useHydrate(dehydratedState, { context })
+        const { data } = useQuery(['string'], () => dataQuery(['string']), {
+          context,
+        })
+        return (
+          <div>
+            <h1>{data}</h1>
+          </div>
+        )
+      }
+
+      const rendered = render(
+        <QueryClientProvider client={queryClientOuter} context={context}>
+          <QueryClientProvider client={queryClientInner}>
+            <Page />
+          </QueryClientProvider>
+        </QueryClientProvider>
+      )
+
+      rendered.getByText('stringCached')
+      await sleep(10)
+      rendered.getByText('string')
+
+      queryClientInner.clear()
+      queryClientOuter.clear()
+    })
   })
 
   describe('ReactQueryCacheProvider with hydration support', () => {
diff --git a/src/reactjs/tests/QueryClientProvider.test.tsx b/src/reactjs/tests/QueryClientProvider.test.tsx
index e451cd97c..e9acb2dc7 100644
--- a/src/reactjs/tests/QueryClientProvider.test.tsx
+++ b/src/reactjs/tests/QueryClientProvider.test.tsx
@@ -135,6 +135,71 @@ describe('QueryClientProvider', () => {
     expect(queryCache.find(key)?.options.cacheTime).toBe(Infinity)
   })
 
+  describe('with custom context', () => {
+    it('uses the correct context', async () => {
+      const key = queryKey()
+
+      const contextOuter = React.createContext<QueryClient | undefined>(
+        undefined
+      )
+      const contextInner = React.createContext<QueryClient | undefined>(
+        undefined
+      )
+
+      const queryCacheOuter = new QueryCache()
+      const queryClientOuter = new QueryClient({ queryCache: queryCacheOuter })
+
+      const queryCacheInner = new QueryCache()
+      const queryClientInner = new QueryClient({ queryCache: queryCacheInner })
+
+      const queryCacheInnerInner = new QueryCache()
+      const queryClientInnerInner = new QueryClient({
+        queryCache: queryCacheInnerInner,
+      })
+
+      function Page() {
+        const { data: testOuter } = useQuery(key, async () => 'testOuter', {
+          context: contextOuter,
+        })
+        const { data: testInner } = useQuery(key, async () => 'testInner', {
+          context: contextInner,
+        })
+        const { data: testInnerInner } = useQuery(
+          key,
+          async () => 'testInnerInner'
+        )
+
+        return (
+          <div>
+            <h1>
+              {testOuter} {testInner} {testInnerInner}
+            </h1>
+          </div>
+        )
+      }
+
+      // contextSharing should be ignored when passing a custom context.
+      const contextSharing = true
+
+      const rendered = render(
+        <QueryClientProvider client={queryClientOuter} context={contextOuter}>
+          <QueryClientProvider client={queryClientInner} context={contextInner}>
+            <QueryClientProvider
+              client={queryClientInnerInner}
+              contextSharing={contextSharing}
+            >
+              <Page />
+            </QueryClientProvider>
+          </QueryClientProvider>
+        </QueryClientProvider>
+      )
+
+      await waitFor(() =>
+        rendered.getByText('testOuter testInner testInnerInner')
+      )
+    })
+  })
+
   describe('useQueryClient', () => {
     test('should throw an error if no query client has been set', () => {
       const consoleMock = jest
diff --git a/src/reactjs/tests/useIsFetching.test.tsx b/src/reactjs/tests/useIsFetching.test.tsx
index 9c91ca25b..cb16bade8 100644
--- a/src/reactjs/tests/useIsFetching.test.tsx
+++ b/src/reactjs/tests/useIsFetching.test.tsx
@@ -1,5 +1,6 @@
 import { fireEvent, waitFor } from '@testing-library/react'
 import React from 'react'
+import { ErrorBoundary } from 'react-error-boundary'
 
 import {
   createQueryClient,
@@ -9,7 +10,7 @@ import {
   setActTimeout,
   sleep,
 } from './utils'
-import { useQuery, useIsFetching, QueryCache } from '../..'
+import { QueryClient, useQuery, useIsFetching, QueryCache } from '../..'
 
 describe('useIsFetching', () => {
   // See https://github.com/tannerlinsley/react-query/issues/105
@@ -156,4 +157,84 @@ describe('useIsFetching', () => {
     await sleep(100)
     expect(isFetchings).toEqual([0, 0, 1, 0])
   })
+
+  describe('with custom context', () => {
+    it('should update as queries start and stop fetching', async () => {
+      const context = React.createContext<QueryClient | undefined>(undefined)
+
+      const queryCache = new QueryCache()
+      const queryClient = new QueryClient({ queryCache })
+      const key = queryKey()
+
+      function Page() {
+        const [ready, setReady] = React.useState(false)
+
+        const isFetching = useIsFetching(undefined, { context: context })
+
+        useQuery(
+          key,
+          async () => {
+            await sleep(1000)
+            return 'test'
+          },
+          {
+            enabled: ready,
+            context,
+          }
+        )
+
+        return (
+          <div>
+            <div>isFetching: {isFetching}</div>
+            <button onClick={() => setReady(true)}>setReady</button>
+          </div>
+        )
+      }
+
+      const rendered = renderWithClient(queryClient, <Page />, {
+        context,
+      })
+
+      await waitFor(() => rendered.getByText('isFetching: 0'))
+      fireEvent.click(rendered.getByText('setReady'))
+      await waitFor(() => rendered.getByText('isFetching: 1'))
+      await waitFor(() => rendered.getByText('isFetching: 0'))
+    })
+
+    it('should throw if the context is not passed to useIsFetching', async () => {
+      const context = React.createContext<QueryClient | undefined>(undefined)
+
+      const queryCache = new QueryCache()
+      const queryClient = new QueryClient({ queryCache })
+      const key = queryKey()
+
+      function Page() {
+        const isFetching = useIsFetching()
+
+        useQuery(key, async () => 'test', {
+          enabled: true,
+          context,
+          useErrorBoundary: true,
+        })
+
+        return (
+          <div>
+            <div>isFetching: {isFetching}</div>
+          </div>
+        )
+      }
+
+      const rendered = renderWithClient(
+        queryClient,
+        <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>
+          <Page />
+        </ErrorBoundary>,
+        {
+          context,
+        }
+      )
+
+      await waitFor(() => rendered.getByText('error boundary'))
+    })
+  })
 })
diff --git a/src/reactjs/tests/useIsMutating.test.tsx b/src/reactjs/tests/useIsMutating.test.tsx
index 19212513d..cf08f96c0 100644
--- a/src/reactjs/tests/useIsMutating.test.tsx
+++ b/src/reactjs/tests/useIsMutating.test.tsx
@@ -8,6 +8,8 @@ import {
   setActTimeout,
   sleep,
 } from './utils'
+import { ErrorBoundary } from 'react-error-boundary'
+import { QueryClient } from '../../core'
 import * as MutationCacheModule from '../../core/mutationCache'
 
 describe('useIsMutating', () => {
@@ -163,4 +165,86 @@ describe('useIsMutating', () => {
     await sleep(20)
     MutationCacheSpy.mockRestore()
   })
+
+  describe('with custom context', () => {
+    it('should return the number of fetching mutations', async () => {
+      const context = React.createContext<QueryClient | undefined>(undefined)
+
+      const isMutatings: number[] = []
+      const queryClient = new QueryClient()
+
+      function IsMutating() {
+        const isMutating = useIsMutating(undefined, { context })
+        isMutatings.push(isMutating)
+        return null
+      }
+
+      function Page() {
+        const { mutate: mutate1 } = useMutation(
+          ['mutation1'],
+          async () => {
+            await sleep(150)
+            return 'data'
+          },
+          { context }
+        )
+        const { mutate: mutate2 } = useMutation(
+          ['mutation2'],
+          async () => {
+            await sleep(50)
+            return 'data'
+          },
+          { context }
+        )
+
+        React.useEffect(() => {
+          mutate1()
+          setActTimeout(() => {
+            mutate2()
+          }, 50)
+        }, [mutate1, mutate2])
+
+        return <IsMutating />
+      }
+
+      renderWithClient(queryClient, <Page />, { context })
+      await waitFor(() => expect(isMutatings).toEqual([0, 1, 1, 2, 2, 1, 0]))
+    })
+
+    it('should throw if the context is not passed to useIsMutating', async () => {
+      const context = React.createContext<QueryClient | undefined>(undefined)
+
+      const isMutatings: number[] = []
+      const queryClient = new QueryClient()
+
+      function IsMutating() {
+        const isMutating = useIsMutating(undefined)
+        isMutatings.push(isMutating)
+        return null
+      }
+
+      function Page() {
+        const { mutate } = useMutation(['mutation'], async () => 'data', {
+          useErrorBoundary: true,
+          context,
+        })
+
+        React.useEffect(() => {
+          mutate()
+        }, [mutate])
+
+        return <IsMutating />
+      }
+
+      const rendered = renderWithClient(
+        queryClient,
+        <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>
+          <Page />
+        </ErrorBoundary>,
+        { context }
+      )
+
+      await waitFor(() => rendered.getByText('error boundary'))
+    })
+  })
 })
diff --git a/src/reactjs/tests/useMutation.test.tsx b/src/reactjs/tests/useMutation.test.tsx
index ff5597ba6..5f973b5e8 100644
--- a/src/reactjs/tests/useMutation.test.tsx
+++ b/src/reactjs/tests/useMutation.test.tsx
@@ -3,7 +3,7 @@ import '@testing-library/jest-dom'
 import React from 'react'
 import { ErrorBoundary } from 'react-error-boundary'
 
-import { useMutation, QueryCache, MutationCache } from '../..'
+import { QueryClient, useMutation, QueryCache, MutationCache } from '../..'
 import { UseMutationResult } from '../types'
 import {
   createQueryClient,
@@ -844,6 +844,71 @@ describe('useMutation', () => {
     expect(onSettledMutate).toHaveBeenCalledTimes(0)
   })
 
+  describe('with custom context', () => {
+    it('should be able to reset `data`', async () => {
+      const context = React.createContext<QueryClient | undefined>(undefined)
+
+      function Page() {
+        const { mutate, data = '', reset } = useMutation(
+          () => Promise.resolve('mutation'),
+          { context }
+        )
+
+        return (
+          <div>
+            <h1 data-testid="title">{data}</h1>
+            <button onClick={() => reset()}>reset</button>
+            <button onClick={() => mutate()}>mutate</button>
+          </div>
+        )
+      }
+
+      const { getByTestId, getByText } = renderWithClient(
+        queryClient,
+        <Page />,
+        { context }
+      )
+
+      expect(getByTestId('title').textContent).toBe('')
+
+      fireEvent.click(getByText('mutate'))
+
+      await waitFor(() => getByTestId('title'))
+
+      expect(getByTestId('title').textContent).toBe('mutation')
+
+      fireEvent.click(getByText('reset'))
+
+      await waitFor(() => getByTestId('title'))
+
+      expect(getByTestId('title').textContent).toBe('')
+    })
+
+    it('should throw if the context is not passed to useMutation', async () => {
+      const context = React.createContext<QueryClient | undefined>(undefined)
+
+      function Page() {
+        const { data = '' } = useMutation(() => Promise.resolve('mutation'))
+
+        return (
+          <div>
+            <h1 data-testid="title">{data}</h1>
+          </div>
+        )
+      }
+
+      const rendered = renderWithClient(
+        queryClient,
+        <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>
+          <Page />
+        </ErrorBoundary>,
+        { context }
+      )
+
+      await waitFor(() => rendered.getByText('error boundary'))
+    })
+  })
+
   it('should call mutate callbacks only for the last observer', async () => {
     const onSuccess = jest.fn()
     const onSuccessMutate = jest.fn()
diff --git a/src/reactjs/tests/useQueries.test.tsx b/src/reactjs/tests/useQueries.test.tsx
index 3ac5e1955..c132a75d2 100644
--- a/src/reactjs/tests/useQueries.test.tsx
+++ b/src/reactjs/tests/useQueries.test.tsx
@@ -1,5 +1,6 @@
 import { waitFor, fireEvent } from '@testing-library/react'
 import React from 'react'
+import { ErrorBoundary } from 'react-error-boundary'
 
 import * as QueriesObserverModule from '../../core/queriesObserver'
 
@@ -13,6 +14,7 @@ import {
   sleep,
 } from './utils'
 import {
+  QueryClient,
   useQueries,
   UseQueryResult,
   QueryCache,
@@ -1056,4 +1058,85 @@ describe('useQueries', () => {
     await sleep(20)
     QueriesObserverSpy.mockRestore()
   })
+
+  describe('with custom context', () => {
+    it('should return the correct states', async () => {
+      const context = React.createContext<QueryClient | undefined>(undefined)
+
+      const key1 = queryKey()
+      const key2 = queryKey()
+      const results: UseQueryResult[][] = []
+
+      function Page() {
+        const result = useQueries({
+          context,
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: async () => {
+                await sleep(5)
+                return 1
+              },
+            },
+            {
+              queryKey: key2,
+              queryFn: async () => {
+                await sleep(10)
+                return 2
+              },
+            },
+          ],
+        })
+        results.push(result)
+        return null
+      }
+
+      renderWithClient(queryClient, <Page />, { context })
+
+      await sleep(30)
+
+      expect(results.length).toBe(3)
+      expect(results[0]).toMatchObject([
+        { data: undefined },
+        { data: undefined },
+      ])
+      expect(results[1]).toMatchObject([{ data: 1 }, { data: undefined }])
+      expect(results[2]).toMatchObject([{ data: 1 }, { data: 2 }])
+    })
+
+    it('should throw if the context is necessary and is not passed to useQueries', async () => {
+      const context = React.createContext<QueryClient | undefined>(undefined)
+
+      const key1 = queryKey()
+      const key2 = queryKey()
+      const results: UseQueryResult[][] = []
+
+      function Page() {
+        const result = useQueries({
+          queries: [
+            {
+              queryKey: key1,
+              queryFn: async () => 1,
+            },
+            {
+              queryKey: key2,
+              queryFn: async () => 2,
+            },
+          ],
+        })
+        results.push(result)
+        return null
+      }
+
+      const rendered = renderWithClient(
+        queryClient,
+        <ErrorBoundary fallbackRender={() => <div>error boundary</div>}>
+          <Page />
+        </ErrorBoundary>,
+        { context }
+      )
+
+      await waitFor(() => rendered.getByText('error boundary'))
+    })
+  })
 })
diff --git a/src/reactjs/tests/utils.tsx b/src/reactjs/tests/utils.tsx
index e6e0bd77f..95d94238a 100644
--- a/src/reactjs/tests/utils.tsx
+++ b/src/reactjs/tests/utils.tsx
@@ -6,6 +6,7 @@ import {
   QueryClient,
   QueryClientConfig,
   QueryClientProvider,
+  ContextOptions,
 } from '../..'
 import * as utils from '../../core/utils'
 
@@ -14,15 +15,23 @@ export function createQueryClient(config?: QueryClientConfig): QueryClient {
   return new QueryClient({ logger: mockLogger, ...config })
 }
 
-export function renderWithClient(client: QueryClient, ui: React.ReactElement) {
+export function renderWithClient(
+  client: QueryClient,
+  ui: React.ReactElement,
+  options: ContextOptions = {}
+) {
   const { rerender, ...result } = render(
-    <QueryClientProvider client={client}>{ui}</QueryClientProvider>
+    <QueryClientProvider client={client} context={options.context}>
+      {ui}
+    </QueryClientProvider>
   )
   return {
     ...result,
     rerender: (rerenderUi: React.ReactElement) =>
       rerender(
-        <QueryClientProvider client={client}>{rerenderUi}</QueryClientProvider>
+        <QueryClientProvider client={client} context={options.context}>
+          {rerenderUi}
+        </QueryClientProvider>
       ),
   }
 }