Use Cases (अपडेट: 2/6/2026)

Claude Code से React और Next.js pagination लागू करें

Claude Code के साथ pagination बनाएं: URL state, API metadata, accessibility और edge-case tests सहित।

Claude Code से React और Next.js pagination लागू करें

Pagination देखने में छोटा UI लगता है: Previous, Next और कुछ page numbers. लेकिन production में असली समस्या button styling नहीं होती. असली समस्या यह होती है कि URL को source of truth कैसे रखा जाए, search filter कैसे बचाए जाएं, गलत page number कैसे संभाला जाए, last page data बदलने पर कैसे ठीक रहे, API metadata भरोसेमंद कैसे हो, और screen reader को current page कैसे बताया जाए.

Claude Code को सिर्फ “React pagination बना दो” कहने पर अक्सर demo ठीक मिलता है, पर production details छूट जाती हैं. ClaudeCodeLab के article archive और admin-style tables में मैंने जो pattern देखा, उसमें page=0 empty list देता था, filter next link में गायब हो जाता था, delete के बाद last page गलत हो जाता था, और current page सिर्फ color से दिखता था. Claude Code इन सबको ठीक कर सकता है, लेकिन prompt में boundary rules पहले से देने होंगे.

यह guide React और Next.js App Router के लिए practical workflow देती है. इसमें prompt, URL design, server-side slicing, JSON API, accessible component, 3 से अधिक use cases, common pitfalls, official links, internal links, CTA और hands-on verification note शामिल हैं. अगर list को लगातार load करना है, तो infinite scroll implementation देखें. API contract के लिए REST API design guide और keyboard/screen reader review के लिए accessibility implementation उपयोगी हैं.

मॉडल पहले चुनें

Pagination के दो आम मॉडल हैं. Offset pagination “page 3, 10 items per page” जैसा request करता है. यह articles, search results, product lists और admin tables के लिए अच्छा है, क्योंकि हर page की shareable URL हो सकती है. Cursor pagination “इस ID के बाद अगले 10 items” जैसा request करता है. यह notifications, audit logs, chats और timelines के लिए बेहतर है, जहां data user के पढ़ते समय बदल सकता है.

इस लेख में offset pagination मुख्य है, क्योंकि SEO, browser history और shared links के लिए यह सरल है. /articles?page=3&q=react जैसी URL सीधे खुल सकती है, teammate को भेजी जा सकती है और reload के बाद state वापस ला सकती है. Real-time feed के लिए Claude Code को cursor model स्पष्ट रूप से बताएं, वरना duplicate या missing records दिख सकते हैं.

मॉडलसही जगहमुख्य जोखिम
OffsetArticles, search, products, admin tablesTotal बदलने पर last page बदल सकता है
CursorNotifications, logs, chat, timelineकिसी भी page पर direct jump कठिन
Infinite scrollFeeds, galleries, related contentBack button, footer और SEO कठिन

Claude Code official Overview इसे ऐसा agentic coding tool बताता है जो codebase पढ़ सकता है, files edit कर सकता है, commands चला सकता है और development tools से जुड़ सकता है. इसलिए prompt में सिर्फ UI नहीं, बल्कि URL, API, accessibility और verification भी शामिल करें.

Claude Code के लिए prompt

Pagination UI, routing, data और accessibility को जोड़ती है. इसलिए first prompt में completion criteria साफ रखें.

React और Next.js App Router में article list pagination implement करें.
Requirements:
- URL के page और q parameters को source of truth मानें
- Modern Next.js में page.tsx के searchParams Promise को support करें
- 10 items per page; page=0 या non-numeric value को page 1 बनाएं
- Requested page last page से बड़ी हो तो last page दिखाएं
- Current page link पर aria-current="page" लगाएं
- Disabled previous/next को clickable link नहीं, span बनाएं
- Existing frontmatter, heroImage, internal links और localized routes न तोड़ें
- Implementation के बाद boundary test cases list करें

Modern Next.js App Router में page.tsx का searchParams Promise की तरह handle किया जाता है. Official page.js reference await के साथ usage दिखाता है. Client components में query पढ़ने के लिए useSearchParams है, लेकिन यह read-only URLSearchParams देता है.

URL state

नीचे वाला example server component के रूप में चलता है. यह q और page पढ़ता है, page number normalize करता है, filter बचाता है और safe values Pagination component को देता है. Data source array है ताकि example copy-paste करके समझा जा सके; real project में यही rules database query में लगाएं.

import { Pagination } from "@/components/Pagination";

const PAGE_SIZE = 10;

const articles = Array.from({ length: 87 }, (_, index) => ({
  id: `article-${index + 1}`,
  title: `Claude Code pagination note ${index + 1}`,
  createdAt: new Date(Date.UTC(2026, 0, index + 1)).toISOString(),
}));

type SearchParams = Promise<{
  page?: string;
  q?: string;
}>;

function readPage(value: string | undefined) {
  const page = Number(value ?? "1");
  return Number.isInteger(page) && page > 0 ? page : 1;
}

export default async function ArticlesPage({
  searchParams,
}: {
  searchParams: SearchParams;
}) {
  const params = await searchParams;
  const query = params.q?.trim() ?? "";
  const requestedPage = readPage(params.page);

  const filtered = query
    ? articles.filter((article) =>
        article.title.toLowerCase().includes(query.toLowerCase()),
      )
    : articles;

  const totalPages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
  const currentPage = Math.min(requestedPage, totalPages);
  const start = (currentPage - 1) * PAGE_SIZE;
  const visibleArticles = filtered.slice(start, start + PAGE_SIZE);

  return (
    <main className="mx-auto max-w-3xl px-4 py-10">
      <h1 className="text-3xl font-bold">Articles</h1>

      <form action="/articles" className="mt-6 flex gap-2">
        <input
          type="search"
          name="q"
          defaultValue={query}
          placeholder="Search articles"
          className="min-w-0 flex-1 rounded border px-3 py-2"
        />
        <button className="rounded bg-black px-4 py-2 text-white">Search</button>
      </form>

      <p className="mt-4 text-sm text-gray-600">
        {filtered.length} articles, page {currentPage} of {totalPages}
      </p>

      <ul className="mt-6 divide-y">
        {visibleArticles.map((article) => (
          <li key={article.id} className="py-4">
            <h2 className="font-semibold">{article.title}</h2>
            <time className="text-sm text-gray-500" dateTime={article.createdAt}>
              {new Intl.DateTimeFormat("en").format(new Date(article.createdAt))}
            </time>
          </li>
        ))}
      </ul>

      <Pagination
        currentPage={currentPage}
        totalPages={totalPages}
        basePath="/articles"
        query={{ q: query || undefined }}
      />
    </main>
  );
}

मुख्य बात यह है कि page number hidden React state में बंद न रहे. अगर state URL में नहीं है, तो refresh, shared link, search indexing और back button कमजोर हो जाते हैं. Query string के लिए standard API URLSearchParams है; behavior की baseline reference MDN URLSearchParams है.

JSON API

अगर mobile app, dashboard widget या client-side table भी वही data चाहता है, तो metadata वाली API दें. User से आया कोई भी pageSize accept न करें.

import type { NextRequest } from "next/server";

const MAX_PAGE_SIZE = 50;

const articles = Array.from({ length: 87 }, (_, index) => ({
  id: `article-${index + 1}`,
  title: `Claude Code pagination note ${index + 1}`,
  createdAt: new Date(Date.UTC(2026, 0, index + 1)).toISOString(),
}));

function readPositiveInt(value: string | null, fallback: number) {
  const parsed = Number(value);
  return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
}

export async function GET(request: NextRequest) {
  const page = readPositiveInt(request.nextUrl.searchParams.get("page"), 1);
  const requestedSize = readPositiveInt(
    request.nextUrl.searchParams.get("pageSize"),
    10,
  );
  const pageSize = Math.min(requestedSize, MAX_PAGE_SIZE);
  const totalItems = articles.length;
  const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
  const safePage = Math.min(page, totalPages);
  const start = (safePage - 1) * pageSize;

  return Response.json({
    items: articles.slice(start, start + pageSize),
    meta: {
      page: safePage,
      pageSize,
      totalItems,
      totalPages,
      hasPreviousPage: safePage > 1,
      hasNextPage: safePage < totalPages,
    },
  });
}

इसे app/api/articles/route.ts में रख सकते हैं. Official Next.js route handler docs app directory में route.ts का pattern समझाते हैं. Real project में database layer visible rows और total count या accepted approximate count लौटाए.

Accessible component

Style बदल सकता है, semantics नहीं. nav पर label दें, current page पर सिर्फ एक aria-current="page" लगाएं, और disabled controls को active link न रखें. MDN aria-current reference pagination links में current page के लिए यही pattern बताता है.

import Link from "next/link";

type QueryValue = string | number | undefined;

type PaginationProps = {
  currentPage: number;
  totalPages: number;
  basePath: string;
  query?: Record<string, QueryValue>;
  previousLabel?: string;
  nextLabel?: string;
};

function normalizePage(page: number, totalPages: number) {
  return Math.min(Math.max(1, page), Math.max(1, totalPages));
}

function visiblePages(currentPage: number, totalPages: number) {
  const pages = new Set([1, totalPages, currentPage - 1, currentPage, currentPage + 1]);
  return [...pages]
    .filter((page) => page >= 1 && page <= totalPages)
    .sort((a, b) => a - b);
}

function hrefForPage(
  basePath: string,
  query: Record<string, QueryValue>,
  page: number,
) {
  const params = new URLSearchParams();

  for (const [key, value] of Object.entries(query)) {
    if (value !== undefined && value !== "") params.set(key, String(value));
  }

  if (page === 1) {
    params.delete("page");
  } else {
    params.set("page", String(page));
  }

  const queryString = params.toString();
  return queryString ? `${basePath}?${queryString}` : basePath;
}

export function Pagination({
  currentPage,
  totalPages,
  basePath,
  query = {},
  previousLabel = "Previous",
  nextLabel = "Next",
}: PaginationProps) {
  if (totalPages <= 1) return null;

  const safePage = normalizePage(currentPage, totalPages);
  const pages = visiblePages(safePage, totalPages);

  return (
    <nav className="mt-8" aria-label="Pagination">
      <ol className="flex flex-wrap items-center gap-2">
        <li>
          {safePage === 1 ? (
            <span aria-disabled="true" className="rounded border px-3 py-2 opacity-50">
              {previousLabel}
            </span>
          ) : (
            <Link
              className="rounded border px-3 py-2 hover:bg-gray-50"
              href={hrefForPage(basePath, query, safePage - 1)}
            >
              {previousLabel}
            </Link>
          )}
        </li>

        {pages.map((page, index) => {
          const previous = pages[index - 1];
          const needsGap = previous !== undefined && page - previous > 1;

          return (
            <li key={page} className="flex items-center gap-2">
              {needsGap ? <span aria-hidden="true">...</span> : null}
              <Link
                aria-current={page === safePage ? "page" : undefined}
                className={
                  page === safePage
                    ? "rounded border bg-black px-3 py-2 text-white"
                    : "rounded border px-3 py-2 hover:bg-gray-50"
                }
                href={hrefForPage(basePath, query, page)}
              >
                {page}
              </Link>
            </li>
          );
        })}

        <li>
          {safePage === totalPages ? (
            <span aria-disabled="true" className="rounded border px-3 py-2 opacity-50">
              {nextLabel}
            </span>
          ) : (
            <Link
              className="rounded border px-3 py-2 hover:bg-gray-50"
              href={hrefForPage(basePath, query, safePage + 1)}
            >
              {nextLabel}
            </Link>
          )}
        </li>
      </ol>
    </nav>
  );
}

Diagram और review

Implementation के बाद Claude Code से छोटा diagram बनवाएं. इससे URL, server page, list और component की जिम्मेदारियां साफ दिखती हैं.

flowchart LR
  A["URL: /articles?page=3&q=react"] --> B["Page searchParams"]
  B --> C["readPage and filter"]
  C --> D["slice visible items"]
  D --> E["Article list"]
  C --> F["Pagination component"]
  F --> A
  C --> G["Optional JSON API meta"]

Review का प्रश्न सरल है: क्या पूरा state URL से reconstruct हो सकता है? अगर हां, तो reload, back button, sharing और SEO अधिक भरोसेमंद होते हैं.

Use cases

पहला use case blog या documentation archive है. जैसे-जैसे Claude Code tutorials बढ़ते हैं, first page हल्का रहता है और पुराने articles direct link से खुलते हैं.

दूसरा ecommerce या SaaS search है. Query, category, price, sort और page URL में रहने चाहिए. Filter बदलते समय page को 1 पर reset करने को prompt में लिखें.

तीसरा admin table है: invoices, users, form submissions और audit records. यहां page-size limit, permission filter और CSV export के साथ consistency जरूरी है.

चौथा learning dashboard है. Reader कई दिनों बाद उसी list पर लौट सकता है. Stable pagination position बचाती है और free cheat sheet या Claude Code consultation जैसी CTA से वापस आना आसान करती है.

Common pitfalls

Incoming page number पर भरोसा न करें. page=-1, page=abc और page=9999 server पर handle करें. Link बनाते समय filters न गिराएं; केवल page बदलें. Current page को सिर्फ color से न दिखाएं; exactly one aria-current="page" रखें. बड़े tables में count cost को भी देखें; COUNT(*) महंगा हो सकता है, इसलिए index, cache या approximate count की जरूरत पड़ सकती है.

History behavior भी तय करें. Low-level pushState() browser session history में entry जोड़ता है, जैसा MDN History pushState बताता है. Next.js में आम तौर पर Link या router.push बेहतर है, लेकिन push और replace का निर्णय जानबूझकर करें.

Verified result

मैंने example को इन cases पर check किया: no page, page=1, page=0, page=abc, page=9999, search with results, search with no results, last page और single-page result. सबसे उपयोगी detail यह थी कि page=1 URL से हट गया और filter के बाद बहुत बड़ी page value last page में clamp हो गई. Shared links साफ हुए और data बदलने के बाद empty screen कम हुई.

Publish से पहले Claude Code से final review कराएं: सिर्फ एक aria-current, boundaries पर disabled previous/next, capped pageSize, preserved filters, await searchParams, और valid TypeScript examples. Pagination छोटा component है, लेकिन archive, search, admin tools और conversion paths पर बड़ा असर डालता है.

#Claude Code #pagination #React #Next.js #UX
मुफ़्त

मुफ़्त PDF: Claude Code cheatsheet

Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.

हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.

Masa

लेखक के बारे में

Masa

Claude Code workflow और team adoption पर काम करने वाला engineer.