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) {
  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 (
    { => (, index) => (
        <div key={index} ref={index + 1 === ? lastElementRef : null}>{}</div>
    <div>{isFetchingNextPage ? <span>Loading more...</span> : null}</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.