Last active
February 7, 2021 19:53
-
-
Save OtayNacef/47fb890f48e795b5066bc3e775a0d803 to your computer and use it in GitHub Desktop.
React Hooks Pagination
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useEffect } from "react"; | |
const LEFT_PAGE = "LEFT"; | |
const RIGHT_PAGE = "RIGHT"; | |
const range = (from, to, step = 1) => { | |
let i = from; | |
const range = []; | |
while (i <= to) { | |
range.push(i); | |
i += step; | |
} | |
return range; | |
}; | |
const Paginations = (props) => { | |
const { | |
totalRecords, | |
pageLimit, | |
pageNeighbours, | |
onPageChanged, | |
currentPage | |
} = props; | |
const [totalPages, setTotalPages] = useState(0); | |
useEffect(() => { | |
setTotalPages(Math.ceil(totalRecords / pageLimit)); | |
}, []); | |
const fetchPageNumbers = () => { | |
const totalNumbers = pageNeighbours * 2 + 3; | |
const totalBlocks = totalNumbers + 2; | |
if (totalPages > totalBlocks) { | |
const startPage = Math.max(2, currentPage - pageNeighbours); | |
const endPage = Math.min(totalPages - 1, currentPage + pageNeighbours); | |
let pages = range(startPage, endPage); | |
const hasLeftSpill = startPage > 2; | |
const hasRightSpill = totalPages - endPage > 1; | |
const spillOffset = totalNumbers - (pages.length + 1); | |
switch (true) { | |
case hasLeftSpill && !hasRightSpill: { | |
const extraPages = range(startPage - spillOffset, startPage - 1); | |
pages = [LEFT_PAGE, ...extraPages, ...pages]; | |
break; | |
} | |
case hasLeftSpill && hasRightSpill: | |
default: { | |
pages = [LEFT_PAGE, ...pages, RIGHT_PAGE]; | |
break; | |
} | |
} | |
return [1, ...pages, totalPages]; | |
} | |
return range(1, totalPages); | |
}; | |
const pages = fetchPageNumbers() || []; | |
return ( | |
<nav aria-label="Countries Pagination"> | |
<ul className="pagination"> | |
{pages.map((page, index) => { | |
if (page === LEFT_PAGE) | |
return ( | |
<li key={index} className="page-item"> | |
<a | |
href="/" | |
className="page-link" | |
aria-label="Previous" | |
onClick={(e) => onPageChanged(e, pageNeighbours * 2 - 1)} | |
> | |
<span aria-hidden="true">«</span> | |
<span className="sr-only">Previous</span> | |
</a> | |
</li> | |
); | |
if (page === RIGHT_PAGE) | |
return ( | |
<li key={index} className="page-item"> | |
<a | |
className="page-link" | |
href="/" | |
aria-label="Next" | |
onClick={(e) => onPageChanged(e, pageNeighbours * 2 + 1)} | |
> | |
<span aria-hidden="true">»</span> | |
<span className="sr-only">Next</span> | |
</a> | |
</li> | |
); | |
return ( | |
<li | |
key={index} | |
className={`page-item${currentPage === page ? " active" : ""}`} | |
> | |
<a | |
className="page-link" | |
href="/" | |
onClick={(e) => onPageChanged(e, page)} | |
> | |
{page} | |
</a> | |
</li> | |
); | |
})} | |
</ul> | |
</nav> | |
); | |
}; | |
export default Paginations; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment