Derive infinite query page params from the server's response
Have getNextPageParam return the next cursor or page from what the server says, and return undefined or null when the server says there are no more pages.
Implementation
- Prefer an API that returns a next cursor, or an explicit
hasMoreor total count. - Return
undefinedornullfromgetNextPageParamwhen there is no next page; that setshasNextPagetofalse. - Avoid inferring the end from
lastPage.length < pageSize; when the last page is exactly full, it fetches one extra empty page. - Include filters in the query key, so changing them starts a new list instead of appending to the old one.
- Set
maxPagesfor very long feeds to bound memory, and providegetPreviousPageParamwhen pages can be dropped from the start. - Disable the load-more control while
isFetchingNextPageis true.
Rationale
The server knows whether more data exists; the client can only guess from page sizes. A guess based on a full last page requests a page that turns out empty, and a guess that assumes short pages mean the end stops early when the server returns a short page for another reason.
Examples
Incorrect (counterexample):
useInfiniteQuery({
queryKey: ['posts'],
queryFn: ({ pageParam }) => fetchPosts({ page: pageParam, limit: 20 }),
initialPageParam: 1,
getNextPageParam: (lastPage, allPages) => (lastPage.length < 20 ? undefined : allPages.length + 1),
});
If there are exactly 40 posts, the query fetches a third, empty page before stopping.
Correct:
useInfiniteQuery({
queryKey: ['posts', { filter }],
queryFn: ({ pageParam }) => fetchPosts({ cursor: pageParam, filter }),
initialPageParam: null as string | null,
getNextPageParam: (lastPage) => lastPage.nextCursor,
});
The server's nextCursor is null when there are no more posts.
Validation
Test with a result count that is an exact multiple of the page size and check that no empty page is requested. Change a filter and check that the list restarts.
Page-size inference is not a violation when the API offers nothing better and an extra empty request is acceptable.