diff --git a/src/core/query.ts b/src/core/query.ts index 336e9b8748..861da15a5d 100644 --- a/src/core/query.ts +++ b/src/core/query.ts @@ -175,7 +175,6 @@ export class Query< this.initialState = config.state || this.getDefaultState(this.options) this.state = this.initialState this.meta = config.meta - this.scheduleGc() } private setOptions( @@ -214,8 +213,12 @@ export class Query< } private optionalRemove() { - if (!this.observers.length && !this.state.isFetching) { - this.cache.remove(this) + if (!this.observers.length) { + if (this.state.isFetching) { + this.scheduleGc() + } else { + this.cache.remove(this) + } } } diff --git a/src/core/tests/query.test.tsx b/src/core/tests/query.test.tsx index 583799cfb3..efdc4894e6 100644 --- a/src/core/tests/query.test.tsx +++ b/src/core/tests/query.test.tsx @@ -544,6 +544,29 @@ describe('query', () => { expect(queryCache.find(key)).toBeUndefined() }) + test('should be garbage collected later when unsubscribed and query is fetching', async () => { + const key = queryKey() + const observer = new QueryObserver(queryClient, { + queryKey: key, + queryFn: async () => { + await sleep(20) + return 'data' + }, + cacheTime: 10, + }) + const unsubscribe = observer.subscribe() + await sleep(20) + expect(queryCache.find(key)).toBeDefined() + observer.refetch() + unsubscribe() + await sleep(10) + // unsubscribe should not remove even though cacheTime has elapsed b/c query is still fetching + expect(queryCache.find(key)).toBeDefined() + await sleep(10) + // should be removed after an additional staleTime wait + expect(queryCache.find(key)).toBeUndefined() + }) + test('should not be garbage collected unless there are no subscribers', async () => { const key = queryKey() const observer = new QueryObserver(queryClient, {