Skip to content

Next.jsサーバーコンポーネントでのクエリパラメータ取得方法

問題の内容

Next.js 13で導入されたApp Routerでは、コンポーネントがデフォルトでサーバーコンポーネントになります。サーバーコンポーネントではcookies()headers()といった関数を使用できますが、クエリパラメータを直接取得する方法は提供されていません。従来のgetServerSidePropsで使えたcontext.query相当の機能をサーバーコンポーネントで実現する方法について説明します。

クエリパラメータとは

URLの?以降に付与されるパラメータ(例: ?productId=123&category=books)で、ページ間の状態保持やフィルタリング処理などに利用されます。

推奨解決方法

ページコンポーネントでの直接取得(公式推奨)

Next.jsの公式ドキュメントで推奨されている方法です。app/[path]/page.tsxなどのページコンポーネントではsearchParamsプロパティを介してクエリパラメータにアクセスできます。

typescript
// app/products/page.tsx
export default function ProductsPage({
  searchParams
}: {
  searchParams?: { [key: string]: string | string[] | undefined };
}) {
  const category = searchParams?.category;
  const page = searchParams?.page || '1';

  return (
    <div>
      <h1>カテゴリ: {category}</h1>
      <p>現在のページ: {page}</p>
    </div>
  );
}

注意点

  • この方法はページコンポーネント(page.tsx)でのみ機能します
  • searchParamsは動的レンダリングを引き起こし、キャッシュされません
  • クエリパラメータの値は常にstringもしくはstring[]型で取得されます

ルートハンドラー内での取得

APIエンドポイント(route.ts)内でクエリパラメータを取得する方法です。

typescript
// app/api/products/route.ts
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  
  const minPrice = searchParams.get('minPrice');
  const maxPrice = searchParams.get('maxPrice');
  
  console.log(`価格範囲: ${minPrice} ~ ${maxPrice}`);
  
  return NextResponse.json({ status: 'success' });
}

ルートハンドラーの利点

  1. サーバーサイドでのみ動作するロジックに最適
  2. 機密データをクライアントに公開せず処理可能
  3. 従来のAPIルート移行が容易

高度な手法

ミドルウェアを利用した全コンポーネントでの取得

任意のサーバーコンポーネントでクエリパラメータを使用する必要がある場合、ミドルウェアでURLをヘッダーに設定する方法があります。

typescript
import { NextRequest, NextResponse } from 'next/server';

export function middleware(request: NextRequest) {
  const headers = new Headers(request.headers);
  headers.set('x-url', request.url);
  
  return NextResponse.next({ headers });
}
typescript
import { headers } from 'next/headers';

export const ProductList = () => {
  const headerList = headers();
  const url = new URL(headerList.get('x-url')!);
  
  const searchTerm = url.searchParams.get('search');
  
  return <div>検索キーワード: {searchTerm}</div>;
};

注意事項

この手法はパフォーマンスに影響を与える可能性があります。必要性を十分に検討した上で使用してください。

サードパーティライブラリの使用 (nuqs)

型安全にクエリパラメータを管理したい場合は、nuqsのようなライブラリも選択肢に入ります。

typescript
import {
  createSearchParamsCache,
  parseAsString,
  parseAsInteger
} from 'nuqs/server';

const searchCache = createSearchParamsCache({
  category: parseAsString,
  page: parseAsInteger.withDefault(1)
});

export default function Page({
  searchParams
}: {
  searchParams: Record<string, string | string[] | undefined>
}) {
  const { category, page } = searchCache.parse(searchParams);
  
  return (
    <div>
      <h2>{category}</h2>
      <p>ページ番号: {page}</p>
    </div>
  );
}

ベストプラクティス

  1. 基本は公式アプローチを優先 - ページコンポーネントでsearchParamsを使用する
  2. データ取得ロジックは分離 - クエリ処理をカスタムフックやサービスに切り出す
  3. 型安全性を確保 - TypeScriptでパラメータ型を厳密に定義する
  4. セキュリティ対策 - ユーザー入力値は必ず検証する
  5. パフォーマンス考慮 - 安易なミドルウェア使用は避ける

Next.js 14以降でも有効なこれらの手法を適切に使い分けることで、サーバーコンポーネントでクエリパラメータを安全かつ効率的に扱うことができます。