blog bg

August 07, 2024

Navigating Pagination in React: Building A Paginator Component

Share what you learn in this blog to prepare for your interview, create your forever-free profile now, and explore how to monetize your valuable knowledge.

Pagination is a crucial aspect of user interface design, especially in web applications where data is presented in chunks. React, being one of the most popular JavaScript libraries for building user interfaces, offers a myriad of solutions for implementing pagination. In this blog post, we'll delve into a specific implementation of a Paginator component in React, exploring its functionality and usage.

 

Understanding the Paginator Component

The Paginator component we'll be discussing is designed to handle navigation between pages of data. It's built using React hooks, specifically useState and useEffect, and leverages Next.js router for navigation. Let's break down its key features:

 

Props

The Paginator component accepts two props:

  1. pageCount: The total number of pages available.
  2. pageNumber: The current page number.

Functionality

  • Page Navigation: The component provides buttons for navigating to the previous and next pages. It dynamically adjusts the page number based on user interaction.
  • Router Integration: It integrates with Next.js router to update the URL query parameters when navigating between pages, ensuring proper handling of browser history.

 

Code Walkthrough

Let's take a closer look at the code:

// Import necessary dependencies
import { inverseQueryBuilder } from '@/utils/inverseQueryBuilder'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'

// Define the interface for props
interface IPaginator {
  pageCount: number
  pageNumber: number
}

// Paginator component definition
export default function Paginator({ pageCount, pageNumber }: IPaginator) {
  // Initialize Next.js router
  const router = useRouter()

  // State for current page number
  const [page, setPage] = useState(pageNumber)

  // Handler for page change
  const onChangeHandler = (selectedItem: { selected: number }) => {
    // Update router query parameters
    router.push(
      router.asPath,
      {
        query: {
          ...inverseQueryBuilder(location.search),
          ...router.query,
          page: selectedItem.selected,
        },
      },
      { shallow: true }
    )
  }

  // Handler for navigating to previous or next page
  const onPageChange = (handler: (selectedItem: { selected: number }) => void, dir: '+' | '-') => {
    if (dir == '+') {
      // Increment page number
      handler({
        selected: (parseInt(inverseQueryBuilder(location.search)?.page as string) || 1) + 1,
      })
    } else if (dir == '-' && page > 0) {
      // Decrement page number
      handler({
        selected: (parseInt(inverseQueryBuilder(location.search)?.page as string) || 1) - 1,
      })
    }
  }

  // Update page state when prop changes
  useEffect(() => {
    setPage(pageNumber)
  }, [pageNumber])

  // Render Paginator component
  return pageCount == null || pageCount <= 0 ? null : (
    <div className="mt-10 flex justify-end">
      {/* Pagination controls */}
      <div className="flex items-center gap-2.5">
        <p className="text-lg text-[#333333]">
          {page} of {pageCount}
        </p>
        <div className="flex items-center gap-3">
          {/* Previous page button */}
          <svg
            width="32"
            height="32"
            viewBox="0 0 18 18"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
            onClick={() => onPageChange(onChangeHandler, '-')}
            className={page <= 1 ? 'pointer-events-none' : 'cursor-pointer'}
          >
            {/* SVG path for previous icon */}
          </svg>

          {/* Next page button */}
          <svg
            width="32"
            height="32"
            viewBox="0 0 18 18"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
            onClick={() => onPageChange(onChangeHandler, '+')}
            className={page >= pageCount ? 'pointer-events-none' : 'cursor-pointer'}
          >
            {/* SVG path for next icon */}
          </svg>
        </div>
      </div>
    </div>
  )
}

 

Conclusion

The Paginator component provides an intuitive way to navigate through paginated data in a React application. Its integration with Next.js router ensures smooth navigation while maintaining the browser history. By understanding its functionality and implementation, developers can enhance user experience when dealing with large datasets spread across multiple pages.

In conclusion, pagination is not just about splitting data into manageable chunks; it's also about providing seamless navigation for users, and the Paginator component serves as a valuable tool in achieving this goal. Whether you're building a simple blog or a complex data-driven application, having a reliable pagination solution can greatly enhance the usability and accessibility of your application.

380 views

Please Login to create a Question