Skip to content

amjed-98/react-ts-pagination

Repository files navigation

react-ts-pagination

NPM

license

Buy Me A Coffee


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.

Pagination demo 2

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.

why react-ts-pagination

  • 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.

Installation

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

Usage

  • With usePagination Hook:

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>
  );
}

Edit Button



  • With useServerPagination Hook:

    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>
);

Edit Button



  • 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>
  );
}

Edit Button


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
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


useServerPagination hook:

Parameters: a single object Parameter with these props:

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

Returns: an Object with these props:

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


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)=>{} 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 `

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 | 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

Pagination demo



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

Releases

No releases published

Packages

No packages published

Languages