Skip to content

Commit

Permalink
feat: query cache provider
Browse files Browse the repository at this point in the history
the query cache now comes from a context, meaning users can easily override and control the cache being used inside their application
  • Loading branch information
Jack Ellis committed May 10, 2020
1 parent ff5d6a7 commit fde53ef
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 5 deletions.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,10 @@ This library is being built and maintained by me, @tannerlinsley and I am always
- [`queryCache.isFetching`](#querycacheisfetching)
- [`queryCache.subscribe`](#querycachesubscribe)
- [`queryCache.clear`](#querycacheclear)
- [`useQueryCache`](#usequerycache)
- [`useIsFetching`](#useisfetching)
- [`ReactQueryConfigProvider`](#reactqueryconfigprovider)
- [`ReactQueryCacheProvider`](#reactquerycacheprovider)
- [`setConsole`](#setconsole)
- [Contributors ✨](#contributors-)

Expand Down Expand Up @@ -2548,6 +2550,18 @@ queryCache.clear()
- `queries: Array<Query>`
- This will be an array containing the queries that were found.
## `useQueryCache`
The `useQueryCache` hook returns the current queryCache instance.
```js
import { useQueryCache } from 'react-query';

const queryCache = useQueryCache()
```
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.
## `useIsFetching`
`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).
Expand Down Expand Up @@ -2608,6 +2622,29 @@ function App() {
- Must be **stable** or **memoized**. Do not create an inline object!
- For non-global properties please see their usage in both the [`useQuery` hook](#usequery) and the [`useMutation` hook](#usemutation).
## `ReactQueryCacheProvider`
`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.
```js
import { ReactQueryCacheProvider, makeQueryCache } from 'react-query';

const queryCache = makeQueryCache()

function App() {
return (
<ReactQueryCacheProvider queryCache={queryCache}>
...
</ReactQueryCacheProvider>
)
}
```
### Options
- `queryCache: Object`
- In instance of queryCache, you can use the `makeQueryCache` factory to create this.
- If not provided, a new cache will be generated.
## `setConsole`
`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.
Expand Down
7 changes: 6 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
export { queryCache } from './queryCache'
export {
queryCache,
makeQueryCache,
ReactQueryCacheProvider,
useQueryCache,
} from './queryCache'
export { ReactQueryConfigProvider } from './config'
export { setFocusHandler } from './setFocusHandler'
export { useIsFetching } from './useIsFetching'
Expand Down
7 changes: 6 additions & 1 deletion src/index.production.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
export { queryCache } from './queryCache'
export {
queryCache,
makeQueryCache,
ReactQueryCacheProvider,
useQueryCache,
} from './queryCache'
export { ReactQueryConfigProvider } from './config'
export { setFocusHandler } from './setFocusHandler'
export { useIsFetching } from './useIsFetching'
Expand Down
19 changes: 18 additions & 1 deletion src/queryCache.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from 'react'
import {
isServer,
functionalUpdate,
Expand All @@ -14,6 +15,20 @@ import { defaultConfigRef } from './config'

export const queryCache = makeQueryCache()

export const queryCacheContext = React.createContext(queryCache)

export function useQueryCache() {
return React.useContext(queryCacheContext)
}

export function ReactQueryCacheProvider({ queryCache, children }) {
return (
<queryCacheContext.Provider value={queryCache || makeQueryCache()}>
{children}
</queryCacheContext.Provider>
)
}

const actionInit = {}
const actionFailed = {}
const actionMarkStale = {}
Expand All @@ -32,7 +47,7 @@ export function makeQueryCache() {
}

const notifyGlobalListeners = () => {
cache.isFetching = Object.values(queryCache.queries).reduce(
cache.isFetching = Object.values(cache.queries).reduce(
(acc, query) => (query.state.isFetching ? acc + 1 : acc),
0
)
Expand Down Expand Up @@ -113,6 +128,7 @@ export function makeQueryCache() {
query.config = { ...query.config, ...config }
} else {
query = makeQuery({
cache,
queryKey,
queryHash,
queryVariables,
Expand Down Expand Up @@ -196,6 +212,7 @@ export function makeQueryCache() {
}

function makeQuery(options) {
const queryCache = options.cache
const reducer = options.config.queryReducer || defaultQueryReducer

const noQueryHash = typeof options.queryHash === 'undefined'
Expand Down
4 changes: 3 additions & 1 deletion src/useBaseQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'

//

import { queryCache } from './queryCache'
import { useQueryCache } from './queryCache'
import { useConfigContext } from './config'
import {
useUid,
Expand All @@ -20,6 +20,8 @@ export function useBaseQuery(queryKey, queryVariables, queryFn, config = {}) {
...config,
}

const queryCache = useQueryCache()

const queryRef = React.useRef()

const newQuery = queryCache._buildQuery(
Expand Down
3 changes: 2 additions & 1 deletion src/useIsFetching.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React from 'react'

import { queryCache } from './queryCache'
import { useQueryCache } from './queryCache'

export function useIsFetching() {
const queryCache = useQueryCache()
const [state, setState] = React.useState({})

React.useEffect(() => {
Expand Down
14 changes: 14 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,20 @@ export interface QueryCache {

export const queryCache: QueryCache

/**
* a factory that creates a new query cache
*/
export function makeQueryCache(): QueryCache

/**
* A hook that uses the query cache context
*/
export function useQueryCache(): QueryCache

export const ReactQueryCacheProvider: React.ComponentType<{
queryCache?: QueryCache
}>

/**
* A hook that returns the number of the quiries that your application is loading or fetching in the background
* (useful for app-wide loading indicators).
Expand Down

0 comments on commit fde53ef

Please sign in to comment.