Customizable React Pagination Component (Typescript)

caner demircicaner demirci
4 min read

https://github.com/canerdemirci/cnr-react-pagination

https://www.npmjs.com/package/cnr-react-pagination

I have written a pagination component in React and published on npm. I aimed to make pagination easier and more useful. The component can navigate to the first page, previous page, next page, last page, and a specific page by number. There are page buttons based on the given range. When a page is selected, the page buttons will be rearranged if necessary. There is also a dropdown menu for selecting pages. The component's style and its icons and button range are customizable.

Here is a sample usage of the pagination component in React:

import Pagination from 'cnr-react-pagination'
import 'cnr-react-pagination/dist/index.css'

const dataLengthPerPage = 8;
const data = [
    {
      "name": "Adeel Solangi",
      "language": "Sindhi",
      "id": "V59OF92YF627HFY0",
      "bio": "Donec lobortis eleifend condimentum. Cras dictum dolor lacinia lectus vehicula rutrum. Maecenas quis nisi nunc. Nam tristique feugiat est vitae mollis. Maecenas quis nisi nunc.",
      "version": 6.1
    },
    // You can add more
];
const [currentPage, setCurrentPage] = useState(1);
const [shownData, setShownData] = useState(data.slice(0, dataLengthPerPage));

useEffect(() => {
  setShownData(data.slice((currentPage - 1) * dataLengthPerPage, currentPage * dataLengthPerPage));
}, [currentPage])

  return (
    <div className="App">
      <table className="dataTable">
        <thead>
          <tr>
            <th>Number</th>
            <th>Name</th>
            <th>Language</th>
            <th>ID</th>
            <th>BIO</th>
            <th>Version</th>
          </tr>
        </thead>
        <tbody>
          {shownData.map((d, i) =>
            <tr key={i}>
              <td>{i+((currentPage-1)*dataLengthPerPage)+1}</td>
              <td>{d.name}</td>
              <td>{d.language}</td>
              <td>{d.id}</td>
              <td>{d.bio}</td>
              <td>{d.version}</td>
            </tr>)}
        </tbody>
      </table>
<br />
      <Pagination
        dataLength={data.length}
        dataLengthPerPage={dataLengthPerPage}
        btn_range={10}
        onChange={(page) => {setCurrentPage(page)}}
        firstBtnIcon={<ImFirst />}
        lastBtnIcon={<ImLast />}
        prevBtnIcon={<ImPrevious2 />}
        nextBtnIcon={<ImNext2 />}
        pageButtonClassName='pagination_4_pageBtn'
        pageButtonSelectedClassName='pagination_4_pageBtn_selected'
        infoSectionClassName='pagination_4_infosection'
      />
<br />
      <Pagination
        dataLength={data.length}
        dataLengthPerPage={dataLengthPerPage}
        onChange={(page) => {setCurrentPage(page)}}
      />

The component's page button arrangement function:

This function rearranges the page buttons when the current page number changes. Its logic is explained in the comments.

function arrangeButtonArray(): number[] {
        /*
        ** We want this arrangment. Selected page is in parentheses.
        ** (Default range limit is 7)
        ** 1, 2, 3, 4, 5, 6, 7 or 16, 17, 18, 19, 20, 21, 22 => If clicked in range limit array remains same.
        ** 1, 2, 3, 4, 5, 6, 7 => (7) => 6, (7), 8, 9, 10, 11, 12
        ** 6, 7, 8, 9, 10, 11, 12 => (6) => 1, 2, 3, 4, 5, (6), 7
        */
        let newArr: number[] = [];

        // If there are as many pages as range limit.
        if (lastPage <= btn_range) {
            return newArr = Array.from({ length: lastPage }, (_, i) => i + 1);
        }

        // * FIRST
        // If selected page is 1.
        if (currentPage === 1) {
            newArr = Array.from({ length: btn_range }, (_, i) => i + 1);
        }
        // * LAST
        // If selected page is last page.
        else if (currentPage === lastPage) {
            newArr = Array.from({ length: btn_range }, (_, i) => i === 0 ? lastPage : lastPage - i).reverse();
        }
        // * PREVIOUS - 6, 7, 8, 9, 10, 11, 12 => (6) => 1, 2, 3, 4, 5, (6), 7
        // If selected page is in button array and is first and not 1.
        else if (currentPage <= buttonArray[0] && currentPage !== 1) {
            let start = Math.max(currentPage - btn_range + 2, 1);
            let end = start + btn_range;

            for (let i = start; i < end; i++) {
                newArr.push(i);
            }
        // * NEXT - 1, 2, 3, 4, 5, 6, 7 => (7) => 6, (7), 8, 9, 10, 11, 12
        // If selected page is in button array and is last and not last page.
        } else if (currentPage >= buttonArray[buttonArray.length - 1] && currentPage !== lastPage) {
            let start = currentPage - 1;
            let end = start + btn_range;

            if (end > lastPage) {
                end = lastPage + 1;
                start = lastPage - btn_range + 1;
            }

            for (let i = start; i < end; i++) {
                newArr.push(i);
            }
        }
        // If selected page is in button array.
        else {
            return [...buttonArray];
        }

        return newArr;
    }

and its using in rendering:

const [buttonArray, setButtonArray] = useState<number[]>(Array.from({ length: btn_range }, (_, i) => i + 1));

useEffect(() => {
        setButtonArray(arrangeButtonArray());
    }, [currentPage]);

{/* Page Buttons */}
                {buttonArray.map(i => <PageButton
                    key={i}
                    pageNumber={i}
                    isSelected={currentPage === i}
                    onClick={() => onChangePage(i)}
                    className={pageButtonClassName}
                    selectedClassName={pageButtonSelectedClassName}
                />)}

You can use the component on your react, next projects: https://www.npmjs.com/package/cnr-react-pagination

You can see the source code of the component and an example project in my GitHub repository: https://github.com/canerdemirci/cnr-react-pagination

0
Subscribe to my newsletter

Read articles from caner demirci directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

caner demirci
caner demirci

Programming is fun. It is nice to spend time with it and not realize how time passes, learning new things... I hope one day I will make awesome things with it.