React × Next.js 環境で react-paginate を使ったページネーションの実装方法をまとめました。
記事一覧や商品リストなど、データを分割して表示したい場合にそのまま流用できるよう、コンポーネント化前提のコード例で紹介します。
📌 使用ツール
- Next.js (App Router)
- TypeScript
- react-paginate
📌 ディレクトリ例
project/
├─ app/
│ ├─ page.tsx // トップページ(呼び出し側)
│ └─ components/
│ └─ PaginatedItems.tsx // ページネーション用コンポーネント
📌 導入手順
① パッケージインストール
npm install react-paginate
# または
yarn add react-paginate
② ページネーション用コンポーネント作成
// app/components/PaginatedItems.tsx
"use client";
import { useState } from "react";
import ReactPaginate from "react-paginate";
// データの型(今回は仮置き)
type Post = {
id: number;
title: string;
};
type PaginatedItemsProps = {
items: Post[]; // ページネーション対象の配列
itemsPerPage: number; // 1ページあたりの件数
};
export function PaginatedItems({ items, itemsPerPage }: PaginatedItemsProps) {
const [itemOffset, setItemOffset] = useState(0);
// 表示範囲を計算
const endOffset = itemOffset + itemsPerPage;
const currentItems = items.slice(itemOffset, endOffset);
// 総ページ数
const pageCount = Math.ceil(items.length / itemsPerPage);
// ページ切り替え時の処理
const handlePageClick = (event: { selected: number }) => {
const newOffset = (event.selected * itemsPerPage) % items.length;
setItemOffset(newOffset);
};
return (
<>
{/* 投稿リスト */}
<div className="grid gap-4 sm:grid-cols-2 md:grid-cols-3">
{currentItems.map((post) => (
<div key={post.id} className="rounded border p-4">
{post.title}
</div>
))}
</div>
{/* ページネーションUI */}
<div className="mt-6 flex justify-center">
<ReactPaginate
breakLabel="..."
nextLabel="next >"
onPageChange={handlePageClick}
pageRangeDisplayed={5}
pageCount={pageCount}
previousLabel="< previous"
renderOnZeroPageCount={null}
// ===== css =====
containerClassName="flex items-center gap-2 justify-center" // 全体を横並び中央
pageLinkClassName="" // 各ページ番号
activeLinkClassName="" // アクティブページ
previousLinkClassName="" // < previous
nextLinkClassName="" // next >
/>
</div>
</>
);
}
③ ページ側で呼び出し
// app/page.tsx
import { PaginatedItems } from "./components/PaginatedItems";
// 仮置きデータ
const dummyPosts = Array.from({ length: 9 }).map((_, i) => ({
id: i + 1,
title: `Post Title ${i + 1}`,
}));
export default function Home() {
return (
<main className="p-8">
<h1 className="mb-4 text-xl font-bold">記事一覧</h1>
// ②で作成したコンポーネントを読み込む
<PaginatedItems items={dummyPosts} itemsPerPage={3} />
</main>
);
}
📌 まとめ
-
react-paginateは配列を.slice()で分割して表示するのが基本 - コンポーネント化しておけばデータ部分(items)を差し替えるだけで使い回すことが可能
- 仮置きデータでUIと動作を作り込んでおき、後でAPIやSupabaseの取得結果に差し替えるとスムーズ