From 076015fee4547e1d9f5322da54ae985e19ba94c9 Mon Sep 17 00:00:00 2001 From: Damian Osipiuk Date: Fri, 5 Aug 2022 00:15:48 +0200 Subject: [PATCH] feat: notify about observer options change --- packages/query-core/src/mutationCache.ts | 7 +++++++ packages/query-core/src/mutationObserver.ts | 9 +++++++++ packages/query-core/src/queryCache.ts | 7 +++++++ packages/query-core/src/queryObserver.ts | 8 ++++++++ .../src/tests/queryObserver.test.tsx | 19 +++++++++++++++++++ .../src/__tests__/useQuery.test.tsx | 18 ++++++++++-------- 6 files changed, 60 insertions(+), 8 deletions(-) diff --git a/packages/query-core/src/mutationCache.ts b/packages/query-core/src/mutationCache.ts index 91a1197abc..f4490c8fd7 100644 --- a/packages/query-core/src/mutationCache.ts +++ b/packages/query-core/src/mutationCache.ts @@ -48,6 +48,12 @@ interface NotifyEventMutationObserverRemoved { observer: MutationObserver } +interface NotifyEventMutationObserverOptionsUpdated { + type: 'observerOptionsUpdated' + mutation?: Mutation + observer: MutationObserver +} + interface NotifyEventMutationUpdated { type: 'updated' mutation: Mutation @@ -59,6 +65,7 @@ type MutationCacheNotifyEvent = | NotifyEventMutationRemoved | NotifyEventMutationObserverAdded | NotifyEventMutationObserverRemoved + | NotifyEventMutationObserverOptionsUpdated | NotifyEventMutationUpdated type MutationCacheListener = (event: MutationCacheNotifyEvent) => void diff --git a/packages/query-core/src/mutationObserver.ts b/packages/query-core/src/mutationObserver.ts index 1ba246fb6d..0e9646955f 100644 --- a/packages/query-core/src/mutationObserver.ts +++ b/packages/query-core/src/mutationObserver.ts @@ -8,6 +8,7 @@ import type { MutationObserverResult, MutationObserverOptions, } from './types' +import { shallowEqualObjects } from './utils' // TYPES @@ -63,7 +64,15 @@ export class MutationObserver< setOptions( options?: MutationObserverOptions, ) { + 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 { diff --git a/packages/query-core/src/queryCache.ts b/packages/query-core/src/queryCache.ts index e4488b3719..3f262672e0 100644 --- a/packages/query-core/src/queryCache.ts +++ b/packages/query-core/src/queryCache.ts @@ -55,6 +55,12 @@ interface NotifyEventQueryObserverResultsUpdated { query: Query } +interface NotifyEventQueryObserverOptionsUpdated { + type: 'observerOptionsUpdated' + query: Query + observer: QueryObserver +} + type QueryCacheNotifyEvent = | NotifyEventQueryAdded | NotifyEventQueryRemoved @@ -62,6 +68,7 @@ type QueryCacheNotifyEvent = | NotifyEventQueryObserverAdded | NotifyEventQueryObserverRemoved | NotifyEventQueryObserverResultsUpdated + | NotifyEventQueryObserverOptionsUpdated type QueryCacheListener = (event: QueryCacheNotifyEvent) => void diff --git a/packages/query-core/src/queryObserver.ts b/packages/query-core/src/queryObserver.ts index 7f66d4b571..1babfb05d7 100644 --- a/packages/query-core/src/queryObserver.ts +++ b/packages/query-core/src/queryObserver.ts @@ -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' diff --git a/packages/query-core/src/tests/queryObserver.test.tsx b/packages/query-core/src/tests/queryObserver.test.tsx index cc1db87d9e..b0164bf9b1 100644 --- a/packages/query-core/src/tests/queryObserver.test.tsx +++ b/packages/query-core/src/tests/queryObserver.test.tsx @@ -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() + }) }) diff --git a/packages/react-query/src/__tests__/useQuery.test.tsx b/packages/react-query/src/__tests__/useQuery.test.tsx index 37ab64707a..6d124914d7 100644 --- a/packages/react-query/src/__tests__/useQuery.test.tsx +++ b/packages/react-query/src/__tests__/useQuery.test.tsx @@ -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 () => {