Next.jsサーバーコンポーネントでのクエリパラメータ取得方法
問題の内容
Next.js 13で導入されたApp Routerでは、コンポーネントがデフォルトでサーバーコンポーネントになります。サーバーコンポーネントではcookies()
やheaders()
といった関数を使用できますが、クエリパラメータを直接取得する方法は提供されていません。従来のgetServerSideProps
で使えたcontext.query
相当の機能をサーバーコンポーネントで実現する方法について説明します。
クエリパラメータとは
URLの?
以降に付与されるパラメータ(例: ?productId=123&category=books
)で、ページ間の状態保持やフィルタリング処理などに利用されます。
推奨解決方法
ページコンポーネントでの直接取得(公式推奨)
Next.jsの公式ドキュメントで推奨されている方法です。app/[path]/page.tsx
などのページコンポーネントではsearchParams
プロパティを介してクエリパラメータにアクセスできます。
// 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
)内でクエリパラメータを取得する方法です。
// 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' });
}
ルートハンドラーの利点
- サーバーサイドでのみ動作するロジックに最適
- 機密データをクライアントに公開せず処理可能
- 従来のAPIルート移行が容易
高度な手法
ミドルウェアを利用した全コンポーネントでの取得
任意のサーバーコンポーネントでクエリパラメータを使用する必要がある場合、ミドルウェアでURLをヘッダーに設定する方法があります。
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 });
}
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
のようなライブラリも選択肢に入ります。
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>
);
}
ベストプラクティス
- 基本は公式アプローチを優先 - ページコンポーネントで
searchParams
を使用する - データ取得ロジックは分離 - クエリ処理をカスタムフックやサービスに切り出す
- 型安全性を確保 - TypeScriptでパラメータ型を厳密に定義する
- セキュリティ対策 - ユーザー入力値は必ず検証する
- パフォーマンス考慮 - 安易なミドルウェア使用は避ける
Next.js 14以降でも有効なこれらの手法を適切に使い分けることで、サーバーコンポーネントでクエリパラメータを安全かつ効率的に扱うことができます。