How to implement infinite scrolling and pagination with Next.js and TanStack Query
Most applications you develop will need data management. As programs continue to scale, the amount of data that needs to be managed is increasing. When an app fails to manage data effectively, it performs poorly.
Paging and infinite scrolling are two popular techniques you can use to optimize application performance. They can help you process existing data more efficiently and enhance the overall user experience.
Pagination and endless scrolling with TanStack Query
TanStack Query - an adaptation of React Query - is a powerful state management library for JavaScript applications. It provides an effective solution for managing application state among other functions, including data-related tasks such as caching.
Pagination involves dividing a large group of data into small pages, allowing users to navigate content in manageable groups using navigation buttons. In contrast, infinite scrolling provides a more dynamic browsing experience. As users scroll, new data is loaded and displayed automatically, eliminating the need for explicit navigation.
Paging and infinite scrolling aim to effectively manage and display large data. Choosing between the two depends on the application's data requirements.
Set up the Next.js project
To get started, create a Next.js project. Install the latest version of Next.js 13 which uses the App folder.
npx create-next-app@latest next-project --app
Next, install the TanStack package in the project using npm, the Node.
npm i @tanstack/react-query
Integrate TanStack query in Next.js app
To integrate TanStack Query in your Next.js project, you need to create and initialize a new instance of TanStack Query in your application's root directory - the layout.js file . To do that, import QueryClient and QueryClientProvider from the TanStack query . Then include the child property with the QueryClientProvider as follows:
"use client" import React from 'react' import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; const metadata = { title: 'Create Next App', description: 'Generated by create next app', }; export default function RootLayout({ children }) { const queryClient = new QueryClient(); return ( {children} ); } export { metadata };
This setting ensures that the TanStack Query has completed accessing the application state.
Implement pagination using the useQuery hook
The useQuery hook fetches and manages data. By providing pagination parameters, such as page numbering, you easily access specific sub-groups of data.
Additionally, this hook provides various options and configurations to customize data fetching functionality, including setting cache options, as well as handling load state efficiently. With these features, you can create an effective pagination experience.
Now to implement pagination in the Next.js app, create the file Pagination/page.js in the src/app directory . Inside this file, create the following imports :
"use client" import React, { useState } from 'react'; import { useQuery} from '@tanstack/react-query'; import './page.styles.css';
Then, define the React function component. Inside this component, you need to define a function that fetches data from the external API. In this case, use the JSONPlaceholder API to fetch a group of posts.
export default function Pagination() { const [page, setPage] = useState(1); const fetchPosts = async () => { try { const response = await fetch(`https://jsonplaceholder.typicode.com/posts? _page=${page}&_limit=10`); if (!response.ok) { throw new Error('Failed to fetch posts'); } const data = await response.json(); return data; } catch (error) { console.error(error); throw error; } }; // thêm code sau vào đây }
Now define the useQuery hook, and define the following parameters as objects:
const { isLoading, isError, error, data } = useQuery({ keepPreviousData: true, queryKey: ['posts', page], queryFn: fetchPosts, });
The keepPreviousData value is true , which ensures that while fetching new data, the app will keep the previous data intact. The queryKey parameter is an array containing the key for this query, so the endpoint and current page are where you want to fetch data for them. Finally, the queryFn parameter , fetchPosts , triggers a function call to fetch the data.
As mentioned initially, this hook provides a number of states that you can open, similar to how you would deconstruct arrays and objects, and then use them to improve the user experience (show proper UI ) while performing the data fetch. These states include isLoading , isError , and more.
To do that, include the following code to show different notification screens based on the current state of the process in progress:
if (isLoading) { return (
Loading.
); } if (isError) { return (
{error.message}
); }
Finally, include this code for the JSX elements that appear on the browser page. This code also serves two different functions:
- After this app fetches posts from the API, they will be in the data variable provided by the useQuery hook . This variable helps manage the state of the application. You can then 'map' the list of posts stored in this variable, and then display them in the browser.
- To add two navigation buttons, Previous and Next , allow users to query and show additional paginated data respectively.
return (
Next.js Pagination
{data && (
{data.map((post) => (
- {post.title}
))}
)} );
Finally, start the programming server.
npm run dev
Then go to http://localhost:3000/Pagination in a browser.
Because you included the Pagination folder in the app folder , Next.js sees it as a route, allowing you to access the page using that URL.
Infinite scrolling using the useInfiniteQuery hook
Infinite scrolling provides a seamless browsing experience. YouTube is an obvious example, it automatically fetches new videos and shows them as you scroll the page.
The useInfiniteQuery hook allows you to implement infinite scrolling by fetching data from a server within pages and automatically fetching and displaying the next page of data when the user scrolls down.
To implement infinite scrolling, add the InfiniteScroll/page.js file in the src/app directory . Then, do the following imports:
"use client" import React, { useRef, useEffect, useState } from 'react'; import { useInfiniteQuery } from '@tanstack/react-query'; import './page.styles.css';
Next, create the React function component. Inside this component, similar to pagination, create a function to fetch the article's data.
export default function InfiniteScroll() { const listRef = useRef(null); const [isLoadingMore, setIsLoadingMore] = useState(false); const fetchPosts = async ({ pageParam = 1 }) => { try { const response = await fetch(`https://jsonplaceholder.typicode.com/posts? _page=${pageParam}&_limit=5`); if (!response.ok) { throw new Error('Failed to fetch posts'); } const data = await response.json(); await new Promise((resolve) => setTimeout(resolve, 2000)); return data; } catch (error) { console.error(error); throw error; } }; // thêm code sau vào đây }
Unlike paging, this code introduces a 2 second delay when fetching data to allow the user to explore the current data while scrolling to trigger re-fetching of a new set of data.
Now, define the useInfiniteQuery hook. When mounting the initial component, this hook will fetch the first page of data from the server. When the user scrolls down, this hook will automatically fetch the next page of data and display it in this element.
const { data, fetchNextPage, hasNextPage, isFetching } = useInfiniteQuery({ queryKey: ['posts'], queryFn: fetchPosts, getNextPageParam: (lastPage, allPages) => { if (lastPage.length < 5) { return undefined; } return allPages.length + 1; }, }); const posts = data ? data.pages.flatMap((page) => page) : [];
The posts variable combines all the posts from different pages into one array, giving a simplified version of the data variable. This allows you to easily map and display individual posts.
To track user scrolling and load more data as the user nears the bottom of the list, you can define a function that uses the Intersection Observer API to detect when elements intersect the frame.
const handleIntersection = (entries) => { if (entries[0].isIntersecting && hasNextPage && !isFetching && !isLoadingMore) { setIsLoadingMore(true); fetchNextPage(); } }; useEffect(() => { const observer = new IntersectionObserver(handleIntersection, { threshold: 0.1 }); if (listRef.current) { observer.observe(listRef.current); } return () => { if (listRef.current) { observer.unobserve(listRef.current); } }; }, [listRef, handleIntersection]); useEffect(() => { if (!isFetching) { setIsLoadingMore(false); } }, [isFetching]);
Finally, include JSX components for the article to appear in the browser.
return (
Infinite Scroll
{posts.map((post) => (
- {post.title}
))}
{isFetching ? 'Fetching.' : isLoadingMore ? 'Loading more.' : null} );
After you have made all the necessary changes, go to http://localhost:3000/InfiniteScroll to see them in action.
It's done! Hope the article is useful to you.
You should read it
- How to implement pagination for app in Vue
- How to paginate pages from any page in Word 2016
- How to page numbering and create Header, Footer in odd and even pages in Word 2007 and 2010
- Are you knowledgeable about Samsung manufacturers
- Super Earth's most dangerous volcano can 'explode' soon causing the biggest eruption in history
- 33 rare photos of very different angles of all things in the world
- Opera Mini is officially available on Windows Phone
- How to look up information of martyrs, find grave martyrs online
- EeePC is discounted by 100 USD
- Instructions for finding F @ st Mobile Techcombank password
- Instructions to fix yellow exclamation computer network with only 3 steps
- The COUNTIFS function, how to use the cell count function according to multiple events in Excel
Maybe you are interested
How to get data from web into Excel
What information does a VPN hide? How does it protect your data?
How to transfer data between 2 Google Drive accounts
6 Data Collecting Apps You Need to Delete for Better Privacy
How to master numerical data in Google Sheets with the AVERAGE function
How to delete white space in a table in Word - Appears right below the data