Blog>
Snippets

Infinite Scrolling with useInfiniteQuery

Implement infinite scrolling for posts in a blog application using the useInfiniteQuery hook, including loading more posts when the user scrolls to the bottom of the page.
import { useInfiniteQuery } from 'react-query';
import React, { useEffect } from 'react';
Import the useInfiniteQuery hook from react-query and useEffect from React.
const fetchPosts = async ({ pageParam = 1 }) => {
  const res = await fetch(`/api/posts?page=${pageParam}`);
  return res.json();
};
Define the fetchPosts function to fetch posts from an API, pageParam sets the current page.
const InfinitePosts = () => {
  const { data, hasNextPage, fetchNextPage, isFetchingNextPage } = useInfiniteQuery('posts', fetchPosts, {
    getNextPageParam: (lastPage, pages) => lastPage.nextPage ?? undefined
  });
In the InfinitePosts component, use the useInfiniteQuery hook to fetch posts and manage pagination.
useEffect(() => {
    const handleScroll = () => {
      if (window.innerHeight + document.documentElement.scrollTop !== document.documentElement.offsetHeight || isFetchingNextPage) return;
      fetchNextPage();
    };
    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, [fetchNextPage, isFetchingNextPage]);
Set up an effect to listen for the scroll event and call fetchNextPage when reaching the bottom of the page.
return (
    <div>
      {data.pages.map((group, i) => (
        <React.Fragment key={i}>
          {group.results.map(post => (
            <p key={post.id}>{post.title}</p>
          ))}
        </React.Fragment>
      ))}
      <div>{isFetchingNextPage ? 'Loading more...' : hasNextPage ? 'Scroll for more posts' : 'No more posts'}</div>
    </div>
  );
};
Render the posts and a loading message or 'no more posts' message based on the fetch state.
export default InfinitePosts;
Export the InfinitePosts component for use in the application.