In React Query, implementing infinite scroll data loading primarily relies on the useInfiniteQuery hook. This hook simplifies handling data requests, storage, and cache updates for infinite scroll scenarios. I will now provide a detailed explanation of how to use this hook to implement infinite scroll data loading.
Step 1: Setting Up the Query Function
First, we need to define a function that fetches data based on the page number. For example, if we want to fetch article data from an API, the function might look like this:
javascriptconst fetchArticles = async ({ pageParam = 1 }) => { const response = await fetch(`https://api.example.com/articles?page=${pageParam}`); return response.json(); }
Here, pageParam is the parameter used for API pagination, initially defaulting to page 1.
Step 2: Using useInfiniteQuery
In the component, we use useInfiniteQuery and pass in the query function we defined earlier:
javascriptimport { useInfiniteQuery } from 'react-query'; const Articles = () => { const { data, error, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage, status, } = useInfiniteQuery('articles', fetchArticles, { getNextPageParam: (lastPage, pages) => lastPage.nextPage ?? false, }); // Other component parts... }
getNextPageParam is an optional configuration that determines how to obtain the parameter for the next page. In this example, we assume the API response includes information about the next page.
Step 3: Implementing Scroll Loading
In the actual UI, we need to add logic to load the next page of data when the user scrolls to the bottom of the page. This is typically combined with a scroll listener:
javascriptuseEffect(() => { 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]);
Step 4: Displaying Data and Loading States
Finally, in your component, you can display data and loading states based on the current state:
javascriptreturn ( <div> {status === 'loading' ? ( <p>Loading...</p> ) : status === 'error' ? ( <p>Error: {error.message}</p> ) : ( <> {data.pages.map((group, i) => ( <React.Fragment key={i}> {group.articles.map(article => ( <p key={article.id}>{article.title}</p> ))} </React.Fragment> ))} <div> {isFetchingNextPage ? 'Loading more...' : hasNextPage ? 'Load More' : 'Nothing more to load'} </div> </> )} </div> );
With this approach, we can implement infinite scroll concisely while maintaining good user experience and performance optimization.