0.0.7 • Published 1 year ago
ts-react-pagination v0.0.7
ts-react-pagination
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.
Note: if you want to have the default styles, you must import the styles file "import 'ts-react-pagination/styles.css'"
. else you'll have to style everything using your own classes or style.
why ts-react-pagination
- This package supports Typescript out of the box, so no need for
npm install @types/ts-react-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 ts-react-pagination
with npm:
npm install ts-react-pagination
with yarn:
yarn add ts-react-pagination
Usage
With usePagination Hook:
import { Pagination, usePagination } from 'ts-react-pagination';
import 'ts-react-pagination/styles.css';
function App() {
const {
currentPageNumber, pageItems, numberOfPages
} = 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}
/>
</div>
);
}
With useServerPagination Hook:
Note: this hook is only used when your Api supports server pagination.
import { Pagination, useServerPagination } from 'ts-react-pagination';
import 'ts-react-pagination/styles.css';
function App() {
const {
pageItems,
isLoading,
currentPageNumber,
} = 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}
/>
</div>
);
}
Passing your own custom props:
import { Pagination } from 'ts-react-pagination';
import 'ts-react-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?
usePagination hook:
Parameters: a single object Parameter with these props:
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 |
Returns: an Object with these props:
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 |
useServerPagination hook:
Parameters: a single object Parameter with these props:
Name | Type | Description |
---|---|---|
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:
Name | Type | Description |
---|---|---|
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 |
Pagination Component:
Props:
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)=>{} | Optional: the handler function to handle changing pages, it gets passed the currentPageNumber and the the dom reference for current page. Note: this is an optinal property, the package already handles changing pages out of the box, but incase you wanted to handle changing pages with your own function handler. |
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/ts-react-pagination.git
cd ts-react-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