Skip to content

Commit

Permalink
feat(queryCache): pass query to subscribers (#765)
Browse files Browse the repository at this point in the history
Any cache update triggered by a query will pass the query as the second argument to subscribers.
This enables executing side-effects for specific query updates.
  • Loading branch information
TuckerWhitehouse authored and tannerlinsley committed Jul 17, 2020
1 parent 3e1880f commit c6e3f8e
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 8 deletions.
5 changes: 3 additions & 2 deletions docs/src/pages/docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -580,15 +580,16 @@ The `subscribe` method can be used to subscribe to the query cache as a whole an
```js
import { queryCache } from 'react-query'

const callback = cache => {}
const callback = (cache, query) => {}

const unsubscribe = queryCache.subscribe(callback)
```
**Options**
- `callback: Function(queryCache) => void`
- `callback: Function(queryCache, query?) => void`
- This function will be called with the query cache any time it is updated via its tracked update mechanisms (eg, `query.setState`, `queryCache.removeQueries`, etc). Out of scope mutations to the queryCache are not encouraged and will not fire subscription callbacks
- Additionally, for updates to the cache triggered by a specific query, the `query` will be passed as the second argument to the callback
**Returns**
Expand Down
4 changes: 2 additions & 2 deletions src/core/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export function makeQuery({
query.dispatch = action => {
query.state = queryReducer(query.state, action)
query.instances.forEach(d => d.onStateUpdate(query.state))
notifyGlobalListeners()
notifyGlobalListeners(query)
}

query.scheduleStaleTimeout = () => {
Expand Down Expand Up @@ -158,7 +158,7 @@ export function makeQuery({
query.cancel()
query.dispatch = noop
delete queryCache.queries[query.queryHash]
notifyGlobalListeners()
notifyGlobalListeners(query)
}

query.subscribe = (onStateUpdate = noop) => {
Expand Down
6 changes: 3 additions & 3 deletions src/core/queryCache.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ export function makeQueryCache({ frozen = isServer, defaultConfig } = {}) {
const globalListeners = []

const configRef = defaultConfig
? { current: { ...defaultConfigRef.current, ...defaultConfig }}
? { current: { ...defaultConfigRef.current, ...defaultConfig } }
: defaultConfigRef

const queryCache = {
queries: {},
isFetching: 0,
}

const notifyGlobalListeners = () => {
const notifyGlobalListeners = query => {
queryCache.isFetching = Object.values(queryCache.queries).reduce(
(acc, query) => (query.state.isFetching ? acc + 1 : acc),
0
)

globalListeners.forEach(d => d(queryCache))
globalListeners.forEach(d => d(queryCache, query))
}

queryCache.subscribe = cb => {
Expand Down
11 changes: 11 additions & 0 deletions src/core/tests/queryCache.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ describe('queryCache', () => {
expect(callback).toHaveBeenCalled()
})

test('should include the queryCache and query when notifying listeners', () => {
const callback = jest.fn()

queryCache.subscribe(callback)

queryCache.prefetchQuery('test', () => 'data')
const query = queryCache.getQuery('test')

expect(callback).toHaveBeenCalledWith(queryCache, query)
})

test('should notify subscribers when new query with initialData is added', async () => {
const callback = jest.fn()

Expand Down
2 changes: 1 addition & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ export interface QueryCache {
{ exact }?: { exact?: boolean }
): void
isFetching: number
subscribe(callback: (queryCache: QueryCache) => void): () => void
subscribe(callback: (queryCache: QueryCache, query?: CachedQuery<unknown>) => void): () => void
clear(options?: { notify?: boolean }): void
resetErrorBoundaries: () => void
}
Expand Down

2 comments on commit c6e3f8e

@vercel
Copy link

@vercel vercel bot commented on c6e3f8e Jul 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tannerlinsley
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TuckerWhitehouse, a new major version was acccidentally published (3.0.0) from the original version of this commit because of the BREAKING CHANGE: none at the bottom, which semantic-version understood as a breaking change, with the label of none 馃槀 . While I should have caught this and is ultimately my fault, for future reference, I would avoid using BREAKING CHANGE: unless a new major version is intended. Either way, I've corrected the problem. Carry on and thanks for the contribution!

Please sign in to comment.