Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/query-core/src/mutationCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ interface NotifyEventMutationObserverRemoved {
observer: MutationObserver<any, any, any>
}

interface NotifyEventMutationObserverOptionsUpdated {
type: 'observerOptionsUpdated'
mutation?: Mutation<any, any, any, any>
observer: MutationObserver<any, any, any, any>
}

interface NotifyEventMutationUpdated {
type: 'updated'
mutation: Mutation<any, any, any, any>
Expand All @@ -59,6 +65,7 @@ type MutationCacheNotifyEvent =
| NotifyEventMutationRemoved
| NotifyEventMutationObserverAdded
| NotifyEventMutationObserverRemoved
| NotifyEventMutationObserverOptionsUpdated
| NotifyEventMutationUpdated

type MutationCacheListener = (event: MutationCacheNotifyEvent) => void
Expand Down
9 changes: 9 additions & 0 deletions packages/query-core/src/mutationObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
MutationObserverResult,
MutationObserverOptions,
} from './types'
import { shallowEqualObjects } from './utils'

// TYPES

Expand Down Expand Up @@ -63,7 +64,15 @@ export class MutationObserver<
setOptions(
options?: MutationObserverOptions<TData, TError, TVariables, TContext>,
) {
const prevOptions = this.options
this.options = this.client.defaultMutationOptions(options)
if (!shallowEqualObjects(prevOptions, this.options)) {
this.client.getMutationCache().notify({
type: 'observerOptionsUpdated',
mutation: this.currentMutation,
observer: this,
})
}
}

protected onUnsubscribe(): void {
Expand Down
7 changes: 7 additions & 0 deletions packages/query-core/src/queryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,20 @@ interface NotifyEventQueryObserverResultsUpdated {
query: Query<any, any, any, any>
}

interface NotifyEventQueryObserverOptionsUpdated {
type: 'observerOptionsUpdated'
query: Query<any, any, any, any>
observer: QueryObserver<any, any, any, any, any>
}

type QueryCacheNotifyEvent =
| NotifyEventQueryAdded
| NotifyEventQueryRemoved
| NotifyEventQueryUpdated
| NotifyEventQueryObserverAdded
| NotifyEventQueryObserverRemoved
| NotifyEventQueryObserverResultsUpdated
| NotifyEventQueryObserverOptionsUpdated

type QueryCacheListener = (event: QueryCacheNotifyEvent) => void

Expand Down
8 changes: 8 additions & 0 deletions packages/query-core/src/queryObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,14 @@ export class QueryObserver<

this.options = this.client.defaultQueryOptions(options)

if (!shallowEqualObjects(prevOptions, this.options)) {
this.client.getQueryCache().notify({
type: 'observerOptionsUpdated',
query: this.currentQuery,
observer: this,
})
}

if (
typeof this.options.enabled !== 'undefined' &&
typeof this.options.enabled !== 'boolean'
Expand Down
19 changes: 19 additions & 0 deletions packages/query-core/src/tests/queryObserver.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -799,4 +799,23 @@ describe('queryObserver', () => {

unsubscribe()
})

test('setOptions should notify cache listeners', async () => {
const key = queryKey()

const observer = new QueryObserver(queryClient, {
queryKey: key,
})

const spy = jest.fn()
const unsubscribe = queryClient.getQueryCache().subscribe(spy)
observer.setOptions({ enabled: false })

expect(spy).toHaveBeenCalledTimes(1)
expect(spy).toHaveBeenCalledWith(
expect.objectContaining({ type: 'observerOptionsUpdated' }),
)

unsubscribe()
})
})
18 changes: 10 additions & 8 deletions packages/react-query/src/__tests__/useQuery.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2149,14 +2149,16 @@ describe('useQuery', () => {
await sleep(20)
unsubscribe()

// 1. Subscribe observer
// 2. Query loading
// 3. Observer loading
// 4. Query success
// 5. Observer success
// 6. Query stale
// 7. Unsubscribe observer
expect(fn).toHaveBeenCalledTimes(7)
// 1. Query added -> loading
// 2. Observer result updated -> loading
// 3. Observer added
// 4. Query updated -> success
// 5. Observer result updated -> success
// 6. Query updated -> stale
// 7. Observer options updated
// 8. Observer result updated -> stale
// 9. Observer options updated
expect(fn).toHaveBeenCalledTimes(9)
})

it('should not re-render when it should only re-render on data changes and the data did not change', async () => {
Expand Down