Skip to content

Commit fde53ef

Browse files
author
Jack Ellis
committed
feat: query cache provider
the query cache now comes from a context, meaning users can easily override and control the cache being used inside their application
1 parent ff5d6a7 commit fde53ef

File tree

7 files changed

+86
-5
lines changed

7 files changed

+86
-5
lines changed

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,8 +313,10 @@ This library is being built and maintained by me, @tannerlinsley and I am always
313313
- [`queryCache.isFetching`](#querycacheisfetching)
314314
- [`queryCache.subscribe`](#querycachesubscribe)
315315
- [`queryCache.clear`](#querycacheclear)
316+
- [`useQueryCache`](#usequerycache)
316317
- [`useIsFetching`](#useisfetching)
317318
- [`ReactQueryConfigProvider`](#reactqueryconfigprovider)
319+
- [`ReactQueryCacheProvider`](#reactquerycacheprovider)
318320
- [`setConsole`](#setconsole)
319321
- [Contributors ✨](#contributors-)
320322

@@ -2548,6 +2550,18 @@ queryCache.clear()
25482550
- `queries: Array<Query>`
25492551
- This will be an array containing the queries that were found.
25502552
2553+
## `useQueryCache`
2554+
2555+
The `useQueryCache` hook returns the current queryCache instance.
2556+
2557+
```js
2558+
import { useQueryCache } from 'react-query';
2559+
2560+
const queryCache = useQueryCache()
2561+
```
2562+
2563+
If you are using the `ReactQueryCacheProvider` to set a custom cache, you cannot simply import `{ queryCache }` any more. This hook will ensure you're getting the correct instance.
2564+
25512565
## `useIsFetching`
25522566
25532567
`useIsFetching` is an optional hook that returns the `number` of the queries that your application is loading or fetching in the background (useful for app-wide loading indicators).
@@ -2608,6 +2622,29 @@ function App() {
26082622
- Must be **stable** or **memoized**. Do not create an inline object!
26092623
- For non-global properties please see their usage in both the [`useQuery` hook](#usequery) and the [`useMutation` hook](#usemutation).
26102624
2625+
## `ReactQueryCacheProvider`
2626+
2627+
`ReactQueryCacheProvider` is an optional provider component for explicitly setting the query cache used by `useQuery`. This is useful for creating component-level caches that are not completely global, as well as making truly isolated unit tests.
2628+
2629+
```js
2630+
import { ReactQueryCacheProvider, makeQueryCache } from 'react-query';
2631+
2632+
const queryCache = makeQueryCache()
2633+
2634+
function App() {
2635+
return (
2636+
<ReactQueryCacheProvider queryCache={queryCache}>
2637+
...
2638+
</ReactQueryCacheProvider>
2639+
)
2640+
}
2641+
```
2642+
2643+
### Options
2644+
- `queryCache: Object`
2645+
- In instance of queryCache, you can use the `makeQueryCache` factory to create this.
2646+
- If not provided, a new cache will be generated.
2647+
26112648
## `setConsole`
26122649
26132650
`setConsole` is an optional utility function that allows you to replace the `console` interface used to log errors. By default, the `window.console` object is used. If no global `console` object is found in the environment, nothing will be logged.

src/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
export { queryCache } from './queryCache'
1+
export {
2+
queryCache,
3+
makeQueryCache,
4+
ReactQueryCacheProvider,
5+
useQueryCache,
6+
} from './queryCache'
27
export { ReactQueryConfigProvider } from './config'
38
export { setFocusHandler } from './setFocusHandler'
49
export { useIsFetching } from './useIsFetching'

src/index.production.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
export { queryCache } from './queryCache'
1+
export {
2+
queryCache,
3+
makeQueryCache,
4+
ReactQueryCacheProvider,
5+
useQueryCache,
6+
} from './queryCache'
27
export { ReactQueryConfigProvider } from './config'
38
export { setFocusHandler } from './setFocusHandler'
49
export { useIsFetching } from './useIsFetching'

src/queryCache.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import React from 'react'
12
import {
23
isServer,
34
functionalUpdate,
@@ -14,6 +15,20 @@ import { defaultConfigRef } from './config'
1415

1516
export const queryCache = makeQueryCache()
1617

18+
export const queryCacheContext = React.createContext(queryCache)
19+
20+
export function useQueryCache() {
21+
return React.useContext(queryCacheContext)
22+
}
23+
24+
export function ReactQueryCacheProvider({ queryCache, children }) {
25+
return (
26+
<queryCacheContext.Provider value={queryCache || makeQueryCache()}>
27+
{children}
28+
</queryCacheContext.Provider>
29+
)
30+
}
31+
1732
const actionInit = {}
1833
const actionFailed = {}
1934
const actionMarkStale = {}
@@ -32,7 +47,7 @@ export function makeQueryCache() {
3247
}
3348

3449
const notifyGlobalListeners = () => {
35-
cache.isFetching = Object.values(queryCache.queries).reduce(
50+
cache.isFetching = Object.values(cache.queries).reduce(
3651
(acc, query) => (query.state.isFetching ? acc + 1 : acc),
3752
0
3853
)
@@ -113,6 +128,7 @@ export function makeQueryCache() {
113128
query.config = { ...query.config, ...config }
114129
} else {
115130
query = makeQuery({
131+
cache,
116132
queryKey,
117133
queryHash,
118134
queryVariables,
@@ -196,6 +212,7 @@ export function makeQueryCache() {
196212
}
197213

198214
function makeQuery(options) {
215+
const queryCache = options.cache
199216
const reducer = options.config.queryReducer || defaultQueryReducer
200217

201218
const noQueryHash = typeof options.queryHash === 'undefined'

src/useBaseQuery.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react'
22

33
//
44

5-
import { queryCache } from './queryCache'
5+
import { useQueryCache } from './queryCache'
66
import { useConfigContext } from './config'
77
import {
88
useUid,
@@ -20,6 +20,8 @@ export function useBaseQuery(queryKey, queryVariables, queryFn, config = {}) {
2020
...config,
2121
}
2222

23+
const queryCache = useQueryCache()
24+
2325
const queryRef = React.useRef()
2426

2527
const newQuery = queryCache._buildQuery(

src/useIsFetching.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import React from 'react'
22

3-
import { queryCache } from './queryCache'
3+
import { useQueryCache } from './queryCache'
44

55
export function useIsFetching() {
6+
const queryCache = useQueryCache()
67
const [state, setState] = React.useState({})
78

89
React.useEffect(() => {

types/index.d.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,20 @@ export interface QueryCache {
699699

700700
export const queryCache: QueryCache
701701

702+
/**
703+
* a factory that creates a new query cache
704+
*/
705+
export function makeQueryCache(): QueryCache
706+
707+
/**
708+
* A hook that uses the query cache context
709+
*/
710+
export function useQueryCache(): QueryCache
711+
712+
export const ReactQueryCacheProvider: React.ComponentType<{
713+
queryCache?: QueryCache
714+
}>
715+
702716
/**
703717
* A hook that returns the number of the quiries that your application is loading or fetching in the background
704718
* (useful for app-wide loading indicators).

0 commit comments

Comments
 (0)