Pagination in React.js (React Query included)

Pagination is a vital component in web development, particularly when handling extensive datasets. In React.js, efficient pagination implementation significantly enhances user experience. This article delves into various methods of setting up pagination in React.js, including leveraging React Query for optimal performance.

Understanding Pagination

Pagination divides large datasets into smaller, manageable pages, improving both navigation and application performance by loading only necessary data chunks.

Why Pagination Matters

Pagination is pivotal for:

  1. Improved Performance: Reduces initial load time by loading only required data.

  2. Enhanced Usability: Facilitates easy navigation through pages.

  3. Better Organization: Organizes content into manageable pages, ideal for large content sets like blogs or product listings.

Implementing Basic Pagination in React

React doesn't offer built-in pagination, but implementing a basic system is straightforward. Maintain page and items per page in component state and slice data array accordingly.

// Basic Pagination in React
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>
 );
};

export default MyComponent;

Customizing Pagination UI

Refactor pagination UI elements into separate components or utilize external libraries for pre-built UI components with page numbers.

// Custom React Pagination Component with Numbers
import React from 'react';

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;

Refer to full article for more code snippets.

Utilizing React Query for Advanced Pagination

React Query simplifies data fetching, caching, and state management, ideal for handling paginated data. Set up React Query, fetch paginated data, and utilize prefetching for seamless pagination.

// Using React Query for Pagination
import React, { useState, useEffect } 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, isFetching } = useQuery({
   queryKey: ['myData', page], 
   queryFn: () => fetchData(page), 
   placeholderData: keepPreviousData,
   staleTime: 5000, // how often the data should automatically be refetched
 });

 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>
 );
};

export default MyComponent;

Exploring React Pagination Packages

Leverage React pagination packages like react-paginate or react-js-pagination for simplified pagination implementation. Additionally, consider UI libraries like Material-UI for pre-built components.

For detailed explanations and additional code snippets, refer to the full article.

Author: Rajae Robinson