Hone logo
Hone
Problems

React Pagination Component Challenge

This challenge requires you to build a reusable pagination component in React using TypeScript. A well-implemented pagination component is crucial for improving user experience by breaking down large datasets into manageable chunks, making it easier for users to navigate and find specific information.

Problem Description

You need to create a functional and user-friendly Pagination component in React. This component will allow users to navigate through a list of items that are divided into multiple pages. The component should display the current page number, the total number of pages, and provide buttons to navigate to the previous and next pages.

Key Requirements:

  • Props: The component should accept the following props:
    • currentPage: A number representing the currently active page (0-indexed).
    • totalPages: A number representing the total number of available pages.
    • onPageChange: A callback function that will be called when the user navigates to a different page. This function should receive the new page number as an argument.
  • Display:
    • Clearly display the current page number and the total number of pages (e.g., "Page 3 of 10").
    • Render a "Previous" button. This button should be disabled if the currentPage is the first page.
    • Render a "Next" button. This button should be disabled if the currentPage is the last page.
  • Interactivity:
    • Clicking the "Previous" button should trigger the onPageChange callback with currentPage - 1.
    • Clicking the "Next" button should trigger the onPageChange callback with currentPage + 1.
  • Styling: While full UI design is not required, the component should be structured semantically and allow for easy styling via CSS classes or props. You can assume basic styling will be applied externally.

Expected Behavior:

  • When currentPage is 0 and totalPages is 10, the "Previous" button should be disabled, and the "Next" button should be enabled.
  • When currentPage is 5 and totalPages is 10, both "Previous" and "Next" buttons should be enabled.
  • When currentPage is 9 and totalPages is 10, the "Previous" button should be enabled, and the "Next" button should be disabled.
  • When totalPages is 1, both "Previous" and "Next" buttons should be disabled.

Edge Cases to Consider:

  • totalPages is 0 or negative (handle gracefully, e.g., render nothing or an appropriate message).
  • currentPage is out of bounds (e.g., less than 0 or greater than or equal to totalPages).

Examples

Example 1:

Input Props:
currentPage: 2
totalPages: 7
onPageChange: (newPage: number) => console.log(`Navigated to page ${newPage}`)

Rendered Output (Conceptual HTML):
<nav aria-label="pagination">
  <button disabled>Previous</button>
  <span>Page 3 of 7</span>
  <button>Next</button>
</nav>

Explanation:
The current page is 2 (0-indexed, so displayed as 3). The total pages are 7.
Since it's not the first page, "Previous" is enabled.
Since it's not the last page, "Next" is enabled.
The `onPageChange` function would be called with `1` if "Previous" is clicked, and `3` if "Next" is clicked.

Example 2:

Input Props:
currentPage: 0
totalPages: 5
onPageChange: (newPage: number) => console.log(`Navigated to page ${newPage}`)

Rendered Output (Conceptual HTML):
<nav aria-label="pagination">
  <button disabled>Previous</button>
  <span>Page 1 of 5</span>
  <button>Next</button>
</nav>

Explanation:
The current page is 0 (displayed as 1). The total pages are 5.
It's the first page, so "Previous" is disabled.
It's not the last page, so "Next" is enabled.

Example 3:

Input Props:
currentPage: 4
totalPages: 5
onPageChange: (newPage: number) => console.log(`Navigated to page ${newPage}`)

Rendered Output (Conceptual HTML):
<nav aria-label="pagination">
  <button>Previous</button>
  <span>Page 5 of 5</span>
  <button disabled>Next</button>
</nav>

Explanation:
The current page is 4 (displayed as 5). The total pages are 5.
It's not the first page, so "Previous" is enabled.
It's the last page, so "Next" is disabled.

Example 4 (Edge Case):

Input Props:
currentPage: 0
totalPages: 1
onPageChange: (newPage: number) => console.log(`Navigated to page ${newPage}`)

Rendered Output (Conceptual HTML):
<nav aria-label="pagination">
  <button disabled>Previous</button>
  <span>Page 1 of 1</span>
  <button disabled>Next</button>
</nav>

Explanation:
There is only one page. Both "Previous" and "Next" buttons should be disabled.
The page number displayed should be 1 (as currentPage is 0).

Constraints

  • The Pagination component must be implemented as a functional component in React.
  • All component logic and props should be typed using TypeScript.
  • Avoid using external pagination libraries. Implement the core logic yourself.
  • The component should be reasonably performant; avoid unnecessary re-renders.

Notes

  • Remember that currentPage is 0-indexed, but users typically expect page numbers to start from 1. You will need to handle this conversion for display.
  • Consider accessibility. Use appropriate ARIA attributes, like aria-label for the navigation, and ensure focus management is handled by the browser or by your component's interaction.
  • Think about how you would integrate this component into a larger application that fetches data and manages its own state for the current page.
Loading editor...
typescript