import React, { useState, useEffect, isValidElement } from "react"; export interface PaginationProps { /** * No of items in each page */ pageSize: number; /** * Initial current page index. Start from 1 */ initialCurrentPage?: number; /** * Total number of rows */ total: number; /** * Callback when page is changed */ onChange?: (page: number) => void; /** * Pagination Component */ component?: | React.FC | React.ComponentClass; } export type PaginationComponentProps = Omit< PaginationResults, "paginationComponent" >; export interface PaginationResults { /** * Current page number */ currentPage: number; /** * Total pages */ totalPages: number; /** * No of items in each page */ pageSize: number; /** * Pagination component */ paginationComponent: React.ReactNode; /** * Navigate to next page */ nextPage: () => void; /** * Navigate to prev page */ prevPage: () => void; /** * Navigate to first page */ goToFirst: () => void; /** * Navigate to last page */ goToLast: () => void; /** * Navigate to specific page */ goToPage: (page: number) => void; } /** * Pagination hook * @param props */ const usePagination = (props: PaginationProps): PaginationResults => { const { initialCurrentPage = 1, pageSize = 10, total = 0, onChange, component = PaginationComponent, } = props; const [currentPage, setCurrentPage] = useState(initialCurrentPage); const totalPages = Math.ceil(total / pageSize); const nextPage = () => setCurrentPage((prev) => Math.min(prev + 1, totalPages)); const prevPage = () => setCurrentPage((prev) => Math.max(prev - 1, 1)); const goToFirst = () => setCurrentPage(1); const goToLast = () => setCurrentPage(totalPages); const goToPage = (page: number) => setCurrentPage(page); useEffect(() => { onChange && onChange(currentPage); }, [currentPage]); const pageProps = { currentPage, totalPages, nextPage, prevPage, goToFirst, goToLast, goToPage, pageSize, }; const paginationComponent = React.createElement(component, pageProps); return { paginationComponent, ...pageProps, }; }; const PaginationComponent: React.FC = ({ currentPage, goToFirst, goToLast, goToPage, totalPages, nextPage, prevPage, }) => { const pages = []; for (let i = 1; i <= totalPages; i++) { const isActive = currentPage === i; pages.push( ); } return (
{pages}
); }; export default usePagination;