Blog>
Snippets

Implementing Custom Loading and Error States for Infinite Scroll

Illustrates how to implement custom loading indicators and handle errors gracefully in a React application utilizing infinite scroll, enhancing the overall user experience.
const { data, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage } = useInfiniteQuery('projects', fetchProjects, { getNextPageParam: (lastPage, pages) => lastPage.nextPage });
Using useInfiniteQuery to fetch data. The `fetchProjects` function should be defined to fetch data. `getNextPageParam` is used to determine the next page parameter.
if (error) return <div>An error occurred: {error.message}</div>;
Displaying an error message if the fetching encounters an error.
const observer = useRef();
const lastElementRef = useCallback(node => {
  if (isFetching) return;
  if (observer.current) observer.current.disconnect();
  observer.current = new IntersectionObserver(entries => {
    if (entries[0].isIntersecting && hasNextPage) {
      fetchNextPage();
    }
  });
  if (node) observer.current.observe(node);
}, [isFetching, fetchNextPage, hasNextPage]);
Setting up an IntersectionObserver to load the next page when the last element is visible on the screen.
return (
  <div>
    {data.pages.map(page => (
      page.data.map((item, index) => (
        <div key={index} ref={index + 1 === page.data.length ? lastElementRef : null}>{item.name}</div>
      ))
    ))}
    <div>{isFetchingNextPage ? <span>Loading more...</span> : null}</div>
  </div>
);
Rendering data and a loading indicator when fetching the next page. The `lastElementRef` is attached to the last item of each page to trigger loading the next page.