初めに
実務でNext.jsを使っているのですが、パスパラメータとクエリパラメータどっちに情報を持たせるべき?そもそも取得の方法ってどうやるの?って悩んだことがあったので今後のためにメモ
パスパラメータ
パスパラメータは、URLの一部として使われるパラメータ。
主に「特定のリソースを一意に識別する」ために使われます。
例)ユーザ一覧から特定のユーザの詳細情報を表示したい時
ユーザIDなど一意になるIDをパスパラメータに設定して、ルーティングさせるのがよくあるパターン
// app/users/[id]/page.tsx
import { useParams } from 'next/navigation';
export default function UserDetailPage() {
const params = useParams();
const userId = params.id;
return <div>User ID: {userId}</div>;
}
クライアントコンポーネントとサーバコンポーネントで取得方法が変わります
クライアントコンポーネント
useParams()フックを使って取得します
'use client';
import { useParams } from 'next/navigation';
export default function ProductInfo() {
const { id } = useParams();
return <div>商品ID: {id}</div>;
}
サーバコンポーネント
props.parmasで取得します
// app/products/[id]/page.tsx
export default function ProductPage({ params }: { params: { id: string } }) {
return <div>商品ID: {params.id}</div>;
}
クエリパラメータ
クエリパラメータは、URLの「?」以降に書かれる情報
表示の状態やソート条件などを指定する
以下のage,sortなどの情報がクエリパラメータ
/users?age=25&sort=desc
こちらもクライアントコンポーネントとサーバコンポーネントで取得方法が変わります
クライアントコンポーネント
useSearchParams()フックを使って取得します
'use client';
import { useSearchParams } from 'next/navigation';
export default function UserFilter() {
const searchParams = useSearchParams();
const age = searchParams.get('age');
return <div>年齢: {age ?? '未指定'}</div>;
}
サーバコンポーネント
props.searchParamsで取得します
// app/users/page.tsx
export default function Page({
searchParams,
}: {
searchParams: { age?: string };
}) {
return <div>年齢: {searchParams.age ?? '未指定'}</div>;
}
どう使い分ける?
RESTfulなAPI設計に基づくと以下のような使い分けになるそうです
パスパラメータ・・・一意になる情報
クエリパラメータ・・表示条件になる情報
ユーザ一覧とユーザ詳細ページを例に考えてみます
一覧ページ
前提:フィルターやソート順を切り替えられる機能がある
ページ番号:2ページ
フィルター条件:年齢=30
ソート条件:降順
の時のURLは以下になる
/users?page=2&age=30&sort=desc
表示に関わる情報なのでクエリパラメータに条件を設定してAPIにリクエストします
詳細ページ
前提:一覧をクリックしたらクリックしたユーザの詳細ページに遷移する
URLは以下になる
/users/123
このページは「誰の情報を見るか」が目的で、リソースを一意に特定しているため、IDをパスパラメータに設定してリクエストするのが推奨されます
参考
最後に
サーバコンポーネントで取得するパターンは実装したことがあるのですが、
クライアントコンポーネントで実装したパターンはなかったので取得方法忘れないようにしたいです。
サーバコンポーネントで取得して子供のクライアントコンポーネントにはpropsでパラメータ渡せると思うので、
- クライアントコンポーネントで取得するパターン
- サーバコンポーネントで取得してpropsでクライアントコンポーネントに渡すパターン
をどうやって使い分けるのかもっと深掘りしていきたいです。