Pagination is a crucial aspect of web development, especially when dealing with large datasets. In React.js, implementing pagination efficiently can greatly enhance the user experience. In this article, we’ll explore various approaches to setting up pagination in React.js including how it could be done utilizing React Query.
Understanding Pagination
Pagination is a technique used to divide a large set of data into smaller, more manageable chunks called pages. This not only makes it easier for users to navigate through the data but also improves the performance of your application by loading only the necessary information.
Why is Pagination Important?
Pagination plays a crucial role in enhancing the user experience of a website or web application. Here are a few reasons why pagination is important:
- Improved Performance: By dividing the data into smaller chunks and loading only the required page, pagination reduces the initial page load time and improves overall performance.
- Enhanced Usability: Users can easily navigate through the data by clicking on page numbers or using previous and next buttons. This makes it easier for them to find the desired content.
- Better Organization: Pagination allows you to organize your content into separate pages, making it more manageable and easier to navigate. This is particularly useful for pages with a large amount of content, such as blog pages or product listings
Basic Pagination in React
React itself doesn’t have a built-in pagination mechanism, but implementing a basic pagination system is relatively straightforward. You can maintain the current page and the number of items per page in your component’s state. Then, you can slice the data array based on these values to display the relevant portion.
Here’s a simple example using React’s useState
hook:
import React, { useState } from 'react';
const MyComponent = ({ data, itemsPerPage }) => {
const [currentPage, setCurrentPage] = useState(1);
const startIndex = (currentPage - 1) * itemsPerPage;
const endIndex = startIndex + itemsPerPage;
const currentData = data.slice(startIndex, endIndex);
return (
<div>
{/* Render your component with currentData */}
{/* some list or grid view here */}
<div>
{/* Pagination UI */}
<button onClick={() => setCurrentPage(currentPage - 1)} disabled={currentPage === 1}>
Previous
</button>
<span>{currentPage}</span>
<button onClick={() => setCurrentPage(currentPage + 1)} disabled={endIndex >= data.length}>
Next
</button>
</div>
</div>
);
};
You could refactor your pagination UI elements to be their own component and you may consider using external libraries which has pre-built UI pagination components that include the page numbers. Of course, you could build your own with custom CSS.
If you need inspiration, here is a general example:
Custom React Pagination Component with Numbers
// Pagination.jsx
import React from 'react';
// import CSS file
const Pagination = ({ totalItems, itemsPerPage, currentPage, onPageChange }) => {
const totalPages = Math.ceil(totalItems / itemsPerPage);
const pageNumbers = Array.from({ length: totalPages }, (_, index) => index + 1);
return (
<div>
<ul className="pagination">
{pageNumbers.map((number) => (
<li key={number} className={number === currentPage ? 'active' : ''}>
<button onClick={() => onPageChange(number)}>{number}</button>
</li>
))}
</ul>
</div>
);
};
export default Pagination;
Custom CSS for React Pagination UI
.pagination {
list-style: none;
display: flex;
padding: 0;
margin: 20px 0;
}
.pagination li {
margin-right: 5px;
}
.pagination button {
background-color: #4caf50;
color: white;
border: 1px solid #4caf50;
padding: 8px 12px;
cursor: pointer;
border-radius: 4px;
}
.pagination button:hover {
background-color: #45a049;
}
.pagination .active button {
background-color: #45a049;
}
This basic approach explained above works well for any dataset, but if you want features such as caching and prefetching, consider using React Query.
Using React Query for Pagination
React Query is a powerful library for managing, caching, and synchronizing server state in React applications. It simplifies data fetching, caching, and state management, making it an excellent choice for handling paginated data.
Setting Up React Query
To use React Query for pagination, you first need to install it. Execute the following command to install the latest version:
npm i @tanstack/react-query
React Query is now at version 5. If you are using an older version for your project and you want to upgrade, visit our migration guide.
To use the React Query, you need to wrap your application with the QueryClientProvider
. In App.jsx
:
import {
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query'
const queryClient = new QueryClient()
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<MyComponent />
</QueryClientProvider>
)
}
Adding Pagination with React Query
Then, you can set up a basic query to fetch your paginated data in your desired component:
// MyComponent.jsx
import React, { useState } from 'react';
import {
useQuery,
QueryClient,
useQueryClient,
keepPreviousData,
} from '@tanstack/react-query'
const fetchData = async (page = 0) => {
const response = await fetch(`https://api.example.com/data?page=${page}`);
return response.json();
};
const MyComponent = () => {
const queryClient = useQueryClient()
const [page, setPage] = useState(0)
const { data, isPending, isError, isPlaceholderData } = useQuery({
queryKey: ['myData', page],
queryFn: () => fetchData(page),
placeholderData: keepPreviousData,
staleTime: 5000, // how often the data should automatically be refetched
});
// prefetching next page
useEffect(() => {
if (!isPlaceholderData && data?.hasMore) {
queryClient.prefetchQuery({
queryKey: ['myData', page + 1],
queryFn: () => fetchData(page + 1),
})
}
}, [data, isPlaceholderData, page, queryClient])
if (isPending) return <div>Loading...</div>;
if (isError) return <div>Error fetching data</div>;
return (
<div>
{/* Render your component with data */}
{/* some list or grid view here */}
<div>
{/* Pagination UI */}
<button onClick={() => setPage((old) => Math.max(old - 1, 0))}
disabled={page === 0}>
Previous
</button>
<span>Current Page: {page + 1}</span>
<button onClick={() => {
setPage((old) => (data?.hasMore ? old + 1 : old))
}}
// Disable the next button until next page is available or there is no more data
disabled={isPlaceholderData || !data?.hasMore}>
Next
</button>
{isFetching ? <span> Loading...</span> : null}
</div>
</div>
);
};
The example above demonstrates how you might paginate data fetched from an API using React Query which allows both prefetching and caching. A similar example can also be viewed here.
Using a React Package for Pagination UI
As mentioned earlier, you can use a React package to simplify the implementation of pagination in your React.js application. Some popular packages for pagination in React.js include react-paginate
, react-js-pagination
, and react-bootstrap-pagination
.
You may also use a React UI Library such as Material-UI which provides a lot of pre-built UI components to speed up your development process. Here is their pagination component. However, if you only need this component for your project, using a UI library might add too much overhead.
If you use TailwindCSS, there are also pre-built components you could utilise and personalize to your liking. For example, Flowbite’s pagination component.
In general, to use a React package for pagination. follow these steps:
- Install the Package: Install the desired pagination package using a package manager like npm, pnpm or yarn.
- Import the Package: Import the necessary components from the package into your React.js application.
- Configure the Pagination Component: Configure the pagination component by providing the required props, such as the total number of records, the number of records per page, and any additional customization options.
- Handle Pagination Events: Implement event handlers to handle pagination events, such as page changes or page size changes. These event handlers should update the state of your application and trigger a re-render of the data.
Conclusion
Pagination in React.js is a fundamental aspect of building performant and user-friendly applications when dealing with large datasets.