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
currentPageis the first page. - Render a "Next" button. This button should be disabled if the
currentPageis the last page.
- Interactivity:
- Clicking the "Previous" button should trigger the
onPageChangecallback withcurrentPage - 1. - Clicking the "Next" button should trigger the
onPageChangecallback withcurrentPage + 1.
- Clicking the "Previous" button should trigger the
- 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
currentPageis 0 andtotalPagesis 10, the "Previous" button should be disabled, and the "Next" button should be enabled. - When
currentPageis 5 andtotalPagesis 10, both "Previous" and "Next" buttons should be enabled. - When
currentPageis 9 andtotalPagesis 10, the "Previous" button should be enabled, and the "Next" button should be disabled. - When
totalPagesis 1, both "Previous" and "Next" buttons should be disabled.
Edge Cases to Consider:
totalPagesis 0 or negative (handle gracefully, e.g., render nothing or an appropriate message).currentPageis out of bounds (e.g., less than 0 or greater than or equal tototalPages).
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
Paginationcomponent 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
currentPageis 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-labelfor 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.