Skip to content

Commit

Permalink
fix(query-core): abort fetch loop for infinite queries if getNextPage…
Browse files Browse the repository at this point in the history
…Param returns null or undefined (#7799)

The `fetchPage` function has a safeguard where it only returns the current data if pageParam == null, however, this means we still stay in the loop and call `getNextPageParam` unnecessarily.

This can be troublesome if you set `pages: Infinity` on queryClient.fetchInfiniteQuery to fetch an arbitrary amount of pages until the natural end is reached by returning null/undefined from getNextPageParam, because it would never actually escape the loop
  • Loading branch information
TkDodo authored Jul 26, 2024
1 parent 34a5672 commit 3ef7887
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 2 deletions.
10 changes: 8 additions & 2 deletions packages/query-core/src/__tests__/queryClient.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -746,12 +746,15 @@ describe('queryClient', () => {

test('should stop prefetching if getNextPageParam returns undefined', async () => {
const key = queryKey()
let count = 0

await queryClient.prefetchInfiniteQuery({
queryKey: key,
queryFn: ({ pageParam }) => String(pageParam),
getNextPageParam: (_lastPage, _pages, lastPageParam) =>
lastPageParam >= 20 ? undefined : lastPageParam + 5,
getNextPageParam: (_lastPage, _pages, lastPageParam) => {
count++
return lastPageParam >= 20 ? undefined : lastPageParam + 5
},
initialPageParam: 10,
pages: 5,
})
Expand All @@ -762,6 +765,9 @@ describe('queryClient', () => {
pages: ['10', '15', '20'],
pageParams: [10, 15, 20],
})

// this check ensures we're exiting the fetch loop early
expect(count).toBe(3)
})
})

Expand Down
3 changes: 3 additions & 0 deletions packages/query-core/src/infiniteQueryBehavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ export function infiniteQueryBehavior<TQueryFnData, TError, TData, TPageParam>(
// Fetch remaining pages
for (let i = 1; i < remainingPages; i++) {
const param = getNextPageParam(options, result)
if (param == null) {
break
}
result = await fetchPage(result, param)
}
}
Expand Down

0 comments on commit 3ef7887

Please sign in to comment.