React Pagination Component with TypeScript
Building a pagination component is a common requirement in web applications dealing with large datasets. This challenge asks you to create a reusable React component that efficiently displays data in manageable chunks, allowing users to navigate through pages. A well-implemented pagination component enhances user experience by preventing overwhelming displays and improving performance.
Problem Description
You are tasked with creating a Pagination component in React using TypeScript. This component should take a totalItems (number), itemsPerPage (number), and currentPage (number) as props and render a set of page numbers and navigation buttons (Previous, Next, First, Last). The component should also provide a callback function onPageChange that is called when a user clicks on a page number or navigation button.
Key Requirements:
- Display Page Numbers: Render page numbers based on
totalItems,itemsPerPage, and the current page. The number of visible page numbers should be limited to a reasonable range (e.g., 5-7 pages visible at a time, with ellipses (...) indicating hidden pages). - Navigation Buttons: Include "Previous," "Next," "First," and "Last" buttons. These buttons should update the
currentPageprop when clicked. - Disabled States: Disable the "Previous" button on the first page, the "Next" button on the last page, the "First" button on the first page, and the "Last" button on the last page.
- Callback Function: Provide an
onPageChangeprop that accepts a function. This function should be called with the newcurrentPagevalue whenever the user navigates to a different page. - Typescript: The component must be written in TypeScript with appropriate type definitions for props and state.
Expected Behavior:
- The component should accurately calculate and display the correct page numbers and navigation buttons based on the provided props.
- Clicking on a page number should update the
currentPageprop and call theonPageChangecallback with the new page number. - Clicking on navigation buttons should update the
currentPageprop and call theonPageChangecallback with the new page number. - Disabled buttons should not be clickable and should visually indicate their disabled state.
Edge Cases to Consider:
totalItemsis 0: The component should render nothing or a message indicating no items are available.itemsPerPageis 0: Handle this gracefully, potentially displaying an error message or defaulting to a reasonable value.currentPageis out of bounds (less than 1 or greater than the total number of pages): Clamp thecurrentPageto the valid range and update the state accordingly.- Large
totalItemsand smallitemsPerPage: Ensure the pagination logic handles this efficiently without rendering an excessive number of page numbers.
Examples
Example 1:
Input: totalItems = 100, itemsPerPage = 10, currentPage = 5, onPageChange = (page) => console.log("Page changed to:", page)
Output: [Page 1] ... [Page 3] [Page 4] [Page 5] [Page 6] [Page 7] ... [Page 10]
Explanation: The component displays page numbers around the current page (5), with ellipses indicating hidden pages. Clicking on any page number or navigation button should call the `onPageChange` function with the new page number.
Example 2:
Input: totalItems = 25, itemsPerPage = 5, currentPage = 1, onPageChange = (page) => console.log("Page changed to:", page)
Output: [Page 1] [Page 2] ... [Page 5]
Explanation: The component displays the first few pages, as the total number of pages is 5. The "Previous" and "First" buttons should be disabled.
Example 3:
Input: totalItems = 15, itemsPerPage = 10, currentPage = 2, onPageChange = (page) => console.log("Page changed to:", page)
Output: [Page 1] [Page 2] ... [Page 3]
Explanation: The component displays page numbers around the current page (2), with ellipses indicating hidden pages.
Constraints
- The component should be reusable and accept props for customization.
- The component should be visually appealing and user-friendly.
- The component should handle edge cases gracefully.
- The component should be performant, even with a large number of items.
totalItems,itemsPerPage, andcurrentPagemust be numbers.currentPagemust be a positive integer.
Notes
- Consider using CSS or a CSS-in-JS library for styling.
- Think about how to handle the display of ellipses (...) to indicate hidden pages.
- Focus on creating a clean and well-structured component with clear type definitions.
- You can use any React hooks (e.g.,
useState,useEffect) to manage the component's state. - The number of visible page numbers can be a configurable prop if you want to extend the component further.