Skip to content

Commit f31e1ed

Browse files
authored
feat: Support the ability to provide a context (#2548)
* Support providing a context * Addressing comments and merge conflicts from rebase
1 parent cba4503 commit f31e1ed

31 files changed

+833
-91
lines changed

.vscode/settings.json

Lines changed: 0 additions & 8 deletions
This file was deleted.

docs/src/pages/devtools.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { ReactQueryDevtools } from 'react-query/devtools'
1818
```
1919

2020
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.
21+
2122
## Floating Mode
2223

2324
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() {
5051
- `position?: "top-left" | "top-right" | "bottom-left" | "bottom-right"`
5152
- Defaults to `bottom-left`
5253
- The position of the React Query logo to open and close the devtools panel
54+
- `context?: React.Context<QueryClient | undefined>`
55+
- Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
5356

5457
## Embedded Mode
5558

docs/src/pages/guides/migrating-to-react-query-4.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,3 +346,90 @@ When using the [functional updater form of setQueryData](../reference/QueryClien
346346
(previousTodo) => previousTodo ? { ...previousTodo, done: true } : undefined
347347
)
348348
```
349+
350+
### Custom Contexts for Multiple Providers
351+
352+
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.
353+
354+
An example:
355+
356+
1) Create a data package.
357+
358+
```tsx
359+
// Our first data package: @my-scope/container-data
360+
361+
const context = React.createContext<QueryClient | undefined>();
362+
const queryCache = new QueryCache()
363+
const queryClient = new QueryClient({ queryCache, context })
364+
365+
366+
export const useUser = () => {
367+
return useQuery(USER_KEY, USER_FETCHER, {
368+
context,
369+
})
370+
}
371+
372+
export const ContainerDataProvider: React.FC = ({ children }) => {
373+
return (
374+
<QueryClientProvider client={queryClient} context={context}>
375+
{children}
376+
</QueryClientProvider>
377+
);
378+
}
379+
380+
```
381+
382+
2) Create a second data package.
383+
384+
```tsx
385+
// Our second data package: @my-scope/my-component-data
386+
387+
const context = React.createContext<QueryClient | undefined>();
388+
const queryCache = new QueryCache()
389+
const queryClient = new QueryClient({ queryCache, context })
390+
391+
392+
export const useItems = () => {
393+
return useQuery(ITEMS_KEY, ITEMS_FETCHER, {
394+
context,
395+
})
396+
}
397+
398+
export const MyComponentDataProvider: React.FC = ({ children }) => {
399+
return (
400+
<QueryClientProvider client={queryClient} context={context}>
401+
{children}
402+
</QueryClientProvider>
403+
);
404+
}
405+
406+
```
407+
408+
3) Use these two data packages in your application.
409+
410+
```tsx
411+
// Our application
412+
413+
import { ContainerDataProvider, useUser } from "@my-scope/container-data";
414+
import { AppDataProvider } from "@my-scope/app-data";
415+
import { MyComponentDataProvider, useItems } from "@my-scope/my-component-data";
416+
417+
<ContainerDataProvider> // <-- Provides container data (like "user") using its own React Query provider
418+
...
419+
<AppDataProvider> // <-- Provides app data using its own React Query provider (unused in this example)
420+
...
421+
<MyComponentDataProvider> // <-- Provides component data (like "items") using its own React Query provider
422+
<MyComponent />
423+
</MyComponentDataProvider>
424+
...
425+
</AppDataProvider>
426+
...
427+
</ContainerDataProvider>
428+
429+
// Example of hooks provided by the "DataProvider" components above:
430+
const MyComponent = () => {
431+
const user = useUser(); // <-- Uses the context specified in ContainerDataProvider.
432+
const items = useItems(); // <-- Uses the context specified in MyComponentDataProvider
433+
...
434+
}
435+
```

docs/src/pages/reference/QueryClientProvider.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@ function App() {
1414
return <QueryClientProvider client={queryClient}>...</QueryClientProvider>
1515
}
1616
```
17+
1718
**Options**
1819

1920
- `client: QueryClient`
2021
- **Required**
2122
- the QueryClient instance to provide
2223
- `contextSharing: boolean`
2324
- defaults to `false`
24-
- 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.
25+
- 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.
26+
- `context?: React.Context<QueryClient | undefined>`
27+
- Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.

docs/src/pages/reference/hydration.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ hydrate(queryClient, dehydratedState, options)
8484
- Optional
8585
- `mutations: MutationOptions` The default mutation options to use for the hydrated mutations.
8686
- `queries: QueryOptions` The default query options to use for the hydrated queries.
87+
- `context?: React.Context<QueryClient | undefined>`
88+
- Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
8789

8890
### Limitations
8991

@@ -108,6 +110,8 @@ useHydrate(dehydratedState, options)
108110
- Optional
109111
- `defaultOptions: QueryOptions`
110112
- The default query options to use for the hydrated queries.
113+
- `context?: React.Context<QueryClient | undefined>`
114+
- Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
111115

112116
## `Hydrate`
113117

@@ -129,3 +133,5 @@ function App() {
129133
- Optional
130134
- `defaultOptions: QueryOptions`
131135
- The default query options to use for the hydrated queries.
136+
- `context?: React.Context<QueryClient | undefined>`
137+
- Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.

docs/src/pages/reference/useIsFetching.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const isFetchingPosts = useIsFetching(['posts'])
1717

1818
- `queryKey?: QueryKey`: [Query Keys](../guides/query-keys)
1919
- `filters?: QueryFilters`: [Query Filters](../guides/filters#query-filters)
20+
- `context?: React.Context<QueryClient | undefined>`
21+
- Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
2022

2123
**Returns**
2224

docs/src/pages/reference/useIsMutating.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const isMutatingPosts = useIsMutating(['posts'])
1717

1818
- `mutationKey?: string | unknown[]`
1919
- `filters?: MutationFilters`: [Mutation Filters](../guides/filters#mutation-filters)
20+
- `context?: React.Context<QueryClient | undefined>`
21+
- Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
2022

2123
**Returns**
2224

docs/src/pages/reference/useMutation.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ mutate(variables, {
8787
- `meta: Record<string, unknown>`
8888
- Optional
8989
- 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`).
90+
- `context?: React.Context<QueryClient | undefined>`
91+
- Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
9092

9193
**Returns**
9294

docs/src/pages/reference/useQueries.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ const results = useQueries({
1616

1717
**Options**
1818

19-
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).
19+
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).
20+
21+
- `context?: React.Context<QueryClient | undefined>`
22+
- Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
2023

2124
**Returns**
2225

docs/src/pages/reference/useQuery.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ const result = useQuery({
184184
- `meta: Record<string, unknown>`
185185
- Optional
186186
- 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`.
187+
- `context?: React.Context<QueryClient | undefined>`
188+
- Use this to use a custom React Query context. Otherwise, `defaultContext` will be used.
187189

188190
**Returns**
189191

0 commit comments

Comments
 (0)