pagination-react-js
Version:
React Pagination Hook, which is lightweight, fast and easy to use.
102 lines (98 loc) • 3.75 kB
JavaScript
// src/package/hooks/usePagination/usePagination.ts
import { useMemo, useState } from "react";
// src/package/utils/generateNumArr/generateNumArr.ts
function generateNumArr(loopStart, loopMax) {
const numArr = [];
for (let i = loopStart; i <= loopMax; i++) {
numArr.push(i);
}
return numArr;
}
// src/package/utils/getOffsetNumbers/getOffsetNumbers.ts
function getOffsetNumbers({
pageNumbers,
firstNumber,
lastNumber,
activeNumber,
offset,
permanentFirstNumber,
permanentLastNumber
}) {
const pageOffsetNumbers = [];
if (!firstNumber || !lastNumber) {
return { pageOffsetNumbers };
}
const additionalOffsetStart = firstNumber + offset * 2 + (permanentFirstNumber ? 1 : 0);
const additionalOffsetEnd = lastNumber - offset * 2 - (permanentLastNumber ? 1 : 0);
for (const pageNumber of pageNumbers) {
if (pageNumber === activeNumber || pageNumber <= activeNumber + offset && pageNumber > activeNumber || pageNumber >= activeNumber - offset && pageNumber < activeNumber || activeNumber - offset <= firstNumber && pageNumber <= additionalOffsetStart || activeNumber + offset >= lastNumber && pageNumber >= additionalOffsetEnd) {
pageOffsetNumbers.push(pageNumber);
}
}
return { pageOffsetNumbers };
}
// src/package/hooks/usePagination/usePagination.ts
function usePagination({
activePage: initialActivePage,
recordsPerPage: initialRecordsPerPage,
totalRecordsLength,
offset,
navCustomPageSteps,
permanentFirstNumber,
permanentLastNumber
}) {
const [activePage, setActivePage] = useState(initialActivePage);
const [recordsPerPage, setRecordsPerPage] = useState(initialRecordsPerPage);
const indexOfLastRecord = (recordsPerPage > totalRecordsLength ? totalRecordsLength : activePage * recordsPerPage) - 1;
const indexOfFirstRecord = recordsPerPage > indexOfLastRecord ? 0 : indexOfLastRecord - recordsPerPage + 1;
if (totalRecordsLength < 0) {
throw new Error("totalRecordsLength cannot be negative");
}
if (recordsPerPage <= 0) {
throw new Error("recordsPerPage must be greater than zero");
}
if (activePage <= 0) {
throw new Error("activePage must be at least 1");
}
const pageNumbers = useMemo(() => generateNumArr(1, Math.ceil(totalRecordsLength / recordsPerPage)), [totalRecordsLength, recordsPerPage]);
const firstPage = useMemo(() => pageNumbers[0], [pageNumbers]);
const lastPage = useMemo(() => pageNumbers[pageNumbers.length - 1], [pageNumbers]);
const { pageOffsetNumbers } = useMemo(
() => getOffsetNumbers({
pageNumbers,
firstNumber: firstPage,
lastNumber: lastPage,
activeNumber: activePage,
offset,
permanentFirstNumber,
permanentLastNumber
}),
[pageNumbers, firstPage, lastPage, activePage, offset, permanentFirstNumber, permanentLastNumber]
);
return {
records: {
perPage: recordsPerPage,
indexOfFirst: indexOfFirstRecord,
indexOfLast: indexOfLastRecord
},
pagination: firstPage && lastPage ? {
activePage,
firstPage,
lastPage,
previousPage: activePage > firstPage ? activePage - 1 : null,
nextPage: activePage < lastPage ? activePage + 1 : null,
customPreviousPage: navCustomPageSteps?.prev && activePage - navCustomPageSteps.prev >= firstPage + 1 ? activePage - navCustomPageSteps.prev : null,
customNextPage: navCustomPageSteps?.next && activePage + navCustomPageSteps.next <= lastPage - 1 ? activePage + navCustomPageSteps.next : null,
pageNumbers: pageOffsetNumbers
} : null,
setRecordsPerPage: (recordsPerPage2) => {
setRecordsPerPage(recordsPerPage2);
},
setActivePage: (pageNumber) => {
setActivePage(pageNumber);
}
};
}
export {
usePagination
};