Pagination in NextJS
Making paths from files
export async function getStaticPaths() {
const files = fs.readdirSync(path.join('posts'))
const numPages = Math.ceil(files.length / POSTS_PER_PAGE)
let paths = []
for (let i = 1; i <= numPages; i++) {
paths.push({
params: { page_index: i.toString() },
})
}
return {
paths,
fallback: false,
}
}
The above code returns this:
[
{params:{pae_index:"1"}}
{params:{pae_index:"2"}}
{params:{pae_index:"3"}}
]
Using paths
We destructor params
export async function getStaticProps({ params }) {
const page = parseInt((params && params.page_index) || 1)
const files = fs.readdirSync(path.join('posts'))
const posts = getPosts();
// Get categories for sidebar
const categories = posts.map((post) => (post.frontmatter.category))
const uniqueCategories = [...new Set(categories)]
const numPages = Math.ceil(files.length / POSTS_PER_PAGE)
const pageIndex = page - 1
const orderedPosts = posts.slice(
pageIndex * POSTS_PER_PAGE,
(pageIndex + 1) * POSTS_PER_PAGE
)
return {
props: {
posts: orderedPosts,
numPages,
currentPage: page,
categories: uniqueCategories,
},
}
}
Frontend Component
export default function BlogPage({ posts, numPages, currentPage, categories }) {
return (
<Layout>
<div className="flex justify-between">
<div className="mr-10 sm:w-full md:w-3/4">
<h1 className="p-5 mb-2 text-5xl font-bold border-b-4 ">Blog</h1>
<div className="grid gap-5 md:grid-col-2 lg:grid-cols-3">
{posts.map((post) => (
<Post key={post.id} post={post} />
))}
</div>
</div>
<div className='hidden md:inline-block md:w-1/4 '>
<CategoryLists categories={categories} />
</div>
</div>
<Pagination currentPage={currentPage} numPages={numPages} />
</Layout>
)
}
Pagination Component
import React from 'react'
import Link from "next/link"
export default function Pagination({ currentPage, numPages }) {
const isFirst = currentPage === 1;
const isLast = currentPage === numPages;
const prevPage = `/blog/page/${currentPage - 1}`;
const nextPage = `/blog/page/${currentPage + 1}`;
if (numPages === 1) return null;
return (
<div className=' flex pl-0 list-none my-2'>
{!isFirst && (
<Link href={prevPage}>
<li className=' relative block py-2 px-3 leading-tight bg-white border border-blue-300 mr-1 hover:bg-green-200
text-blue-800 cursor-pointer'>Previous</li>
</Link>
)}
//
// Below is a super cool trick for dynamically generating page numbers that you can use to bring you to that corresponding page
//
{Array.from({ length: numPages }, (_, i) => {
if (i === 0 || i === numPages - 1 || i === currentPage - 1 || i === currentPage || i === currentPage + 1) {
// The above method only lists the first previous next and last pages I love this TRICK!!!
// Alternatively you can just list all the pages
{Array.from({ length: numPages }, (_, i) => (
// We do plus one because the array starts at zero and there is no page zero
<Link href={`/blog/page/${i + 1}`} key={`page-${i}`}>
<li className='relative block py-2 px-3 leading-tight bg-white border border-blue-300 text-blue-800 mr-1 hover:bg-green-200 cursor-pointer'>
{i + 1}
</li>
</Link>
))}
{!isLast && (
<Link href={nextPage}>
<li className=' relative block py-2 px-3 leading-tight bg-white border border-blue-300 text-blue-800 mr-1 hover:bg-green-200
cursor-pointer'>Next</li>
</Link>
)}
</div>
)
}