

A React.ts Component to render pagination in a simple and Declarative way.
By installing the package you'll have this default pagination look, but you can easilly overwrite it using your own classes and styles.
/styles.css'"`. else you'll have to style everything using your own classes or style.
- This package supports Typescript out of the box, so no need for
npm install @types/react-ts-pagination .
- Exposes a two hooks
usePagination
, useServerPagination
that take cares of all the boilerplate for handling pagination states all in one line.
- Heavlly tested for all possible edge cases and prone to future error, so releasing a broken version of this package is highlly unlikely.
- Strongly typed using advanced typescript to narrow down your types and avoid passing wrong prop or parameter type, which gives you nice auto-completion.
Installation
Install react-ts-pagination
with npm:
npm install react-ts-pagination
with yarn:
yarn add react-ts-pagination
Usage
import { Pagination, usePagination } from 'react-ts-pagination
';
import 'react-ts-pagination
/styles.css';
function App() {
const { currentPageNumber, pageItems, numberOfPages, handlePageChange } = usePagination({
items,
itemsPerPage: 8,
});
return (
<div className='App'>
<Table>
{pageItems.map((page) => (
<tr key={page.id}>
<td>{page.id}</td>
<td>{page.first_name}</td>
<td>{page.last_name}</td>
<td>{page.email}</td>
<td>{page.phone}</td>
</tr>
))}
</Table>
<Pagination
currentPageNumber={currentPageNumber}
numberOfPages={numberOfPages}
onPageChange={handlePageChange}
/>
</div>
);
}

-
Note: this hook is only used when your Api supports server pagination.
import { Pagination, useServerPagination } from 'react-ts-pagination
';
import 'react-ts-pagination
/styles.css';
function App() {
const {
pageItems,
isLoading,
currentPageNumber,
handlePageChange
} = useServerPagination<Repo[]>({
url: 'https://api.github.com/orgs/GSG-G11/repos',
searchParams: { page: 'page', perPage: 'per_page' },
itemsPerPage: 5,
numberOfPages: 12,
});
return (
<div className='App'>
{isLoading ? (
<Skeleton />
) : (
<Table tableHeaders={tableHeaders}>
{pageItems?.map(({ id, name, description, owner, visibility }) => (
<tr key={id}>
<td>{id}</td>
<td>{name}</td>
<td>{owner.login}</td>
<td>{description?.slice(0, 20)}</td>
<td>{visibility}</td>
</tr>
))}
</Table>
)}
<Pagination
currentPageNumber={currentPageNumber}
numberOfPages={numberOfPages}
onPageChange={handlePageChange}
/>
</div>
);
}

-
Passing your own custom props:
import { Pagination } from 'react-ts-pagination
';
import 'react-ts-pagination
/styles.css';
const ITEMS_PER_PAGE = 10;
const numberOfPages = Math.ceil(items.length / ITEMS_PER_PAGE);
function App() {
const [pageItems, setPageItems] = useState < typeof items > [];
const currentPageNumber = useRef(1);
const handlePageChange = (pageNumber: number, pageRef: HTMLSpanElement | undefined) => {
const FIRST_PAGE_NUMBER = 1;
const LAST_PAGE_NUMBER = numberOfPages;
const isFirstPage = pageNumber + 1 === FIRST_PAGE_NUMBER;
const isLastPage = pageNumber - 1 === LAST_PAGE_NUMBER;
if (isLastPage || isFirstPage) return;
const start = (pageNumber - 1) * ITEMS_PER_PAGE;
const end = pageNumber * ITEMS_PER_PAGE;
currentPageNumber.current = pageNumber;
setPageItems(items.slice(start, end));
};
useEffect(() => {
const start = (currentPageNumber.current - 1) * ITEMS_PER_PAGE;
const end = currentPageNumber.current * ITEMS_PER_PAGE;
setPageItems(items.slice(start, end));
}, []);
return (
<div className='App'>
<Table>
{pageItems.map((page) => (
<tr key={page.id}>
<td>{page.id}</td>
<td>{page.first_name}</td>
<td>{page.last_name}</td>
<td>{page.email}</td>
<td>{page.phone}</td>
</tr>
))}
</Table>
<Pagination
currentPageNumber={currentPageNumber.current}
numberOfPages={numberOfPages}
onPageChange={handlePageChange}
/>
</div>
);
}

How to use?
Parameters: a single object Parameter with these props:
items | Array | Required: The Array that you want the paginate on. |
initialPageNumber | Number | Optional: The initial page selected. Default is 1 |
ItemsPerPage | Number | Optional: the number of items to display on each page. Default is 10 |
Returns: an Object with these props:
pageItems | Array | The current items state, for the current page number selected |
currentPageNumber | Number | The page number state |
numberOfPages | Number | The computed number of total pages that should be rendered, depending on the passed items array length |
handlePageChange | Funtion | the handler function to handle changing pages, it expects pageNumber and pageRef to be passed as parameters |
Parameters: a single object Parameter with these props:
url | string | Required: The endpoint for your Api (without the search quries). |
searchParams | Object | Required: an object that contains The search queries for your Api. page: a string that tells the server which page number you want to retrieve. perPage: a string that tells the server how many items to retrieve for each page}` |
initialPageNumber | Number | Optional: The initial page selected. Default is 1 |
ItemsPerPage | Number | Required: The number of items to display on each page. Default is 10 |
Returns: an Object with these props:
isLoading | Boolean | A boolean that presents the state of of the request |
isError | Boolean | A boolean that indicates if error accured or not while fetching the page |
error | object | A standard error object that changes for each page request |
currentPageNumber | Number | The page number state |
handlePageChange | Funtion | the handler function to handle changing pages, it expects pageNumber and pageRef to be passed as parameters |
Props:
currentPageNumber | Number | Required: The current page number state. You can either get it from usePagination hook or you can pass you own currentPageNumber state. |
numberOfPages | Number | Required: The number of total pages that should be generated. You can either get it from usePagination hook or you can pass you own numberOfPages state. |
onPageChange | Function: (page,pageRef)=>{} | Required: the handler function to handle changing pages, it gets passed the currentPageNumber and the the dom reference for current page. |
nextLabel | String or Refrence to A Component | Optional: The next button text label. Default is : ❯ |
nextBtnClass | String | Optional: A class name to apply to the next button. Default is btn |
prevLabel | String or Refrence to A Component | Optional: The prev button text label. Default is : ❮ |
prevBtnClass | String | Optional: A class name to apply to the prev button. Default is btn |
pageStyle | Object | Optional: The defualt page style object with color and backgroundColor properties. Default is:undefined |
activePageSyle | Object | Optional: The acitve page style object with color and background propeties. Default is undefined |
pageClass | String | Optional: A class name to apply to each page. The default class is page |
activePageClass | String | Optional: A class name to to apply to the current acitve page or the page that being hovered. Default is active-page |
paginationContainerClass | String | Optional: A class name to apply to the parent container for the whole component. Default is pagination |
pagesContianerClass | String | Optional: A class name to apply to the direct parent of the pages. Default is pages |
Demo
To run the demo locally, clone the repository and move into it:
git clone git@github.com:amjed-98/react-ts-pagination
.git
cd react-ts-pagination
Install dependencies:
npm install | yarn
preview the Demo
npm run demo | yarn demo
Open your browser and go to http://127.0.0.1:5173/src/demo/index.html
Run the tests
npm run test | yarn test
Run the tests in the browser with nice UI presentation
npm run test:ui | yarn test:ui