React
Beginner
1 min read
Pagination and Infinite Scroll with TanStack Query
Example
import { useInfiniteQuery } from '@tanstack/react-query';
import { useRef, useEffect } from 'react';
async function fetchPage({ pageParam = 1 }) {
const res = await fetch(`/api/posts?page=${pageParam}&limit=10`);
if (!res.ok) throw new Error('Fetch failed');
return res.json(); // { data: [], nextPage: number | null }
}
function InfinitePostList() {
const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
isLoading,
} = useInfiniteQuery({
queryKey: ['posts'],
queryFn: fetchPage,
getNextPageParam: lastPage => lastPage.nextPage ?? undefined,
});
// Intersection Observer sentinel
const sentinelRef = useRef(null);
useEffect(() => {
const el = sentinelRef.current;
if (!el || !hasNextPage) return;
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) fetchNextPage();
});
observer.observe(el);
return () => observer.unobserve(el);
}, [hasNextPage, fetchNextPage]);
if (isLoading) return <p>Loading…</p>;
const posts = data.pages.flatMap(page => page.data);
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
<li ref={sentinelRef}>
{isFetchingNextPage ? 'Loading more…' : hasNextPage ? '' : 'All loaded'}
</li>
</ul>
);
}
Related Resources
React Reference
Complete tag & property list
React How-To Guides
Step-by-step practical guides
React Exercises
Practice what you've learned
More in React
This is the last lesson in this section.
Create a free account to earn a certificate