Skip to content

Commit 7432998

Browse files
committed
fix: make sure to remove the correct query from cache
1 parent 2a9b8d5 commit 7432998

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

src/core/queryCache.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,17 @@ export class QueryCache extends Subscribable<QueryCacheListener> {
6565
}
6666

6767
remove(query: Query<any, any>): void {
68-
if (this.queriesMap[query.queryHash]) {
68+
const queryInMap = this.queriesMap[query.queryHash]
69+
70+
if (queryInMap) {
6971
query.destroy()
70-
delete this.queriesMap[query.queryHash]
72+
7173
this.queries = this.queries.filter(x => x !== query)
74+
75+
if (queryInMap === query) {
76+
delete this.queriesMap[query.queryHash]
77+
}
78+
7279
this.notify(query)
7380
}
7481
}

src/react/tests/useQuery.test.tsx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,55 @@ describe('useQuery', () => {
522522
expect(states[4]).toMatchObject({ isLoading: false, isSuccess: true })
523523
})
524524

525+
it.only('should not get into an infinite loop when removing a query with cacheTime 0 and rerendering', async () => {
526+
const key = queryKey()
527+
const states: UseQueryResult<string>[] = []
528+
529+
function Page() {
530+
const [, rerender] = React.useState({})
531+
532+
const state = useQuery(
533+
key,
534+
async () => {
535+
await sleep(5)
536+
return 'data'
537+
},
538+
{
539+
cacheTime: 0,
540+
}
541+
)
542+
543+
states.push(state)
544+
545+
const { remove } = state
546+
547+
React.useEffect(() => {
548+
setActTimeout(() => {
549+
remove()
550+
rerender({})
551+
}, 20)
552+
}, [remove])
553+
554+
return null
555+
}
556+
557+
renderWithClient(queryClient, <Page />)
558+
559+
await sleep(100)
560+
561+
expect(states.length).toBe(5)
562+
// First load
563+
expect(states[0]).toMatchObject({ isLoading: true, isSuccess: false })
564+
// First success
565+
expect(states[1]).toMatchObject({ isLoading: false, isSuccess: true })
566+
// Switch
567+
expect(states[2]).toMatchObject({ isLoading: false, isSuccess: true })
568+
// Second load
569+
expect(states[3]).toMatchObject({ isLoading: true, isSuccess: false })
570+
// Second success
571+
expect(states[4]).toMatchObject({ isLoading: false, isSuccess: true })
572+
})
573+
525574
it('should fetch when refetchOnMount is false and nothing has been fetched yet', async () => {
526575
const key = queryKey()
527576
const states: UseQueryResult<string>[] = []

0 commit comments

Comments
 (0)