はじめに
Next.jsでWebアプリを開発している中でページネーションの実装が必要になったので、まとめました。
Next.jsでページネーションを実装
ページネーションのコンポーネントが受け取る変数は以下を指定します。
currentPage: 現在表示するページ番号
limit: 一件あたりに表示する件数
count: 全件数
path: ページネーションを呼び出すページパス
全件数から一件あたりに表示する件数を割って表示するトータルのページを算出します。ページネーションのページ番号は最大5つまで表示するようにしています。
ちなみに以下の例はデザインをあてていないので、よしなにCSSを適用する必要があります。前・次のリンクは現在表示しているページによって非活性にしているので、その部分はTailwind CSSを使ってます。
import React from "react";
type Props = {
currentPage: number;
limit: number;
count: number;
path: string;
};
export default function Pagination({currentPage, limit, count, path}: Props) {
const totalPages = Math.ceil(count / limit);
let startPage = Math.max(1, currentPage - 2);
let endPage = Math.min(totalPages, currentPage + 2);
if (currentPage <= 3) {
endPage = Math.min(5, totalPages);
} else if (currentPage >= totalPages - 2) {
startPage = totalPages - 4;
}
const pageNumbers = [];
for (let i = startPage; i <= endPage; i++) {
pageNumbers.push(i);
}
return (
<div>
<a href={`${path}?p=${currentPage - 1}`} aria-label="Previous Page">
<button
className={`${
currentPage === 1 || count < limit ? "cursor-not-allowed" : ""
}`}
disabled={currentPage === 1}
>
<
</button>
</a>
{pageNumbers.map((number) => (
<a key={number} href={`${path}?p=${number}`}>
<button
className={`${
currentPage === number ? "bg-indigo-500 text-white" : ""
}`}
>
{number}
</button>
</a>
))}
<a href={`${path}?p=${currentPage + 1}`} aria-label="Next Page">
<button
className={`${
currentPage === totalPages || count < limit ? "cursor-not-allowed" : ""
}`}
disabled={currentPage === totalPages}
>
>
</button>
</a>
</div>
);
};
ページネーションコンポーネントの呼び出しは、それぞれ必要なPropsを指定してあげます。
<Pagination
currentPage={currentPage}
limit={limit}
count={count}
path="/articles"
/>
おわりに
次はSSG用に/articles/page/2のような静的化できるページネーションを実装したいです。