Use Cases

How to Implement Pagination with Claude Code

Learn how to implement pagination using Claude Code. Includes practical code examples and step-by-step guidance.

ページネーション実装をClaude Codeで効率化する

ページネーションは一見シンプルですが、UIコンポーネント、API設計、クエリ最適化と幅広い知識が求められます。Claude Codeなら、要件を伝えるだけでフロントエンドからバックエンドまで一貫した実装を生成できます。

オフセットベースのページネーション

もっとも基本的なパターンです。Claude Codeに次のように依頼します。

> ページネーション付きの記事一覧コンポーネントをReactで作って。
> 1ページ10件、ページ番号表示、前後移動ボタンあり。
interface PaginationProps {
  currentPage: number;
  totalPages: number;
  onPageChange: (page: number) => void;
}

export function Pagination({ currentPage, totalPages, onPageChange }: PaginationProps) {
  const pages = Array.from({ length: totalPages }, (_, i) => i + 1);

  // 表示するページ番号を絞る(現在ページの前後2ページ)
  const visiblePages = pages.filter(
    (p) => p === 1 || p === totalPages || Math.abs(p - currentPage) <= 2
  );

  return (
    <nav className="flex items-center gap-1">
      <button
        onClick={() => onPageChange(currentPage - 1)}
        disabled={currentPage === 1}
        className="px-3 py-1 rounded disabled:opacity-50"
      >
        Previous
      </button>

      {visiblePages.map((page, i) => {
        // 省略記号の表示
        const prev = visiblePages[i - 1];
        const showEllipsis = prev && page - prev > 1;

        return (
          <span key={page}>
            {showEllipsis && <span className="px-2">...</span>}
            <button
              onClick={() => onPageChange(page)}
              className={`px-3 py-1 rounded ${
                page === currentPage ? "bg-blue-600 text-white" : "hover:bg-gray-100"
              }`}
            >
              {page}
            </button>
          </span>
        );
      })}

      <button
        onClick={() => onPageChange(currentPage + 1)}
        disabled={currentPage === totalPages}
        className="px-3 py-1 rounded disabled:opacity-50"
      >
        Next
      </button>
    </nav>
  );
}

カーソルベースのページネーション

大量データの場合はカーソルベースが効率的です。APIとフロントエンドの両方を一度に生成できます。

// APIルート(Next.js App Router)
import { db } from "@/lib/database";

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const cursor = searchParams.get("cursor");
  const limit = parseInt(searchParams.get("limit") || "20");

  const items = await db.post.findMany({
    take: limit + 1, // 次ページの存在確認用に1件多く取得
    ...(cursor && {
      cursor: { id: cursor },
      skip: 1,
    }),
    orderBy: { createdAt: "desc" },
  });

  const hasMore = items.length > limit;
  const data = hasMore ? items.slice(0, -1) : items;
  const nextCursor = hasMore ? data[data.length - 1].id : null;

  return Response.json({ data, nextCursor, hasMore });
}

無限スクロールの実装

Intersection Observer APIを使った無限スクロールも、Claude Codeなら簡潔に実装できます。

import { useEffect, useRef, useState, useCallback } from "react";

interface Item {
  id: string;
  title: string;
}

export function InfiniteList() {
  const [items, setItems] = useState<Item[]>([]);
  const [cursor, setCursor] = useState<string | null>(null);
  const [hasMore, setHasMore] = useState(true);
  const [loading, setLoading] = useState(false);
  const loaderRef = useRef<HTMLDivElement>(null);

  const loadMore = useCallback(async () => {
    if (loading || !hasMore) return;
    setLoading(true);

    const params = new URLSearchParams({ limit: "20" });
    if (cursor) params.set("cursor", cursor);

    const res = await fetch(`/api/items?${params}`);
    const data = await res.json();

    setItems((prev) => [...prev, ...data.data]);
    setCursor(data.nextCursor);
    setHasMore(data.hasMore);
    setLoading(false);
  }, [cursor, hasMore, loading]);

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting) loadMore();
      },
      { threshold: 0.1 }
    );

    if (loaderRef.current) observer.observe(loaderRef.current);
    return () => observer.disconnect();
  }, [loadMore]);

  return (
    <div>
      {items.map((item) => (
        <div key={item.id} className="p-4 border-b">
          {item.title}
        </div>
      ))}
      <div ref={loaderRef} className="p-4 text-center">
        {loading && "Loading..."}
        {!hasMore && "All items displayed"}
      </div>
    </div>
  );
}

基本的な使い方はClaude Codeの入門ガイドを、プロンプトの工夫はプロンプトを改善する5つのTipsをご覧ください。

Zusammenfassung

Claude Codeを使えば、オフセット型、カーソル型、無限スクロールなど、要件に合ったページネーションを短時間で実装できます。APIからUIまで一貫した設計が得られるのが大きなメリットです。

詳しくはClaude Code公式ドキュメントをご覧ください。

#Claude Code #pagination #React #API design #UX