A React 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.
Note: if you want to have the default styles, you must import the styles file "import 'react-ts-pagination/styles.css'"
, else you'll have to style everything using your own classes or style.
- Supports Typescript out of the box, so you can forget about
npm install @types/react-ts-pagination .
- Supports client-side pagination using
usePagination
hook. - Supports server-side pagination using
useServerPagination
hook. - Heavily tested using unit tests for all possible edge cases and is immune to future errors, so releasing a broken version of this package is highly unlikely.
- highly flexible with the right amount of abstraction so you can use the package without the hooks and provide your own props and styles.
- Strongly typed using advanced typescript to narrow down your types and avoid passing the wrong prop or parameter type, which gives you nice auto-completion.
Install react-ts-pagination
with npm:
npm install react-ts-pagination
with yarn:
yarn add react-ts-pagination
with pnpm:
pnpm install react-ts-pagination
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: because this hook uses react query under the hood you must wrap you component with the provider to use this hook.
import { Pagination, useServerPagination, Provider } from 'react-ts-pagination';
import 'react-ts-pagination/styles.css';
function App() {
const fetchData = async (page: number) => {
const data = await (await fetch(`https://api.github.com/orgs/GSG-G11/repos?page=${page}&per_page=10`)).json();
return data;
};
const { pageItems, isFetching, currentPageNumber, handlePageChange } = useServerPagination<Repo[]>({
queryFunction: fetchData,
});
return (
<div className='App'>
{isFetching ? (
<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>
);
}
export default () => (
<Provider>
<App />
</Provider>
);
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>
);
}
Name | Type | Description |
---|---|---|
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 |
Name | Type | Description |
---|---|---|
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: (pageNumber:number, pageRef:RefObject)=> void |
the handler function to handle changing pages, it expects pageNumber and the page dom Reference to be passed as parameters |
Name | Type | Description |
---|---|---|
queryFunction |
Function |
Required: The function that the query will use to request data, it expects the page number to be passed as a parameter. |
initialPageNumber |
Number |
Optional: The initial page selected. Default is 1 |
cacheTime |
number |
Optional: The time in milliseconds after data is considered stale Default is 10_000 |
Name | Type | Description |
---|---|---|
isFetching |
Boolean |
A boolean that presents the state of of the request |
status |
string |
A string that presents the state of of the request(loading |
isError |
Boolean |
A boolean that indicates if error occurred or not while fetching the page. |
error |
object |
A standard error object if an error occurred while fetching pages. |
currentPageNumber |
Number |
The page number state |
handlePageChange |
Function |
the handler function to handle changing pages, it expects pageNumber and pageRef to be passed as parameters |
Name | Type | Description |
---|---|---|
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: An standard inline style object to style pages. Default is: {} |
activePageSyle |
Object |
Optional: An standard inline style object to style current active page. Default is: {} |
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 |
buildPageText |
Funciton: (pageNumber:number) => number | string |
Optional: A function that will be called inside each page element to render the inner text for that page element. Default is: (pageNumber) => pageNumber ` |
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 | pnpm install
preview the Demo
npm run demo | yarn demo | pnpm 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 | pnpm test
Run the tests in the browser with nice UI presentation
npm run test:ui | yarn test:ui | pnpm test:ui