0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js + react-paginate で記事一覧ページにページネーションを実装する方法

Posted at

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の取得結果に差し替えるとスムーズ
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?