paramsって何? URLとの関係を初心者向けに図で解説
Next.jsを勉強していると、突然出てくる
paramsという言葉。
コードを見るとparams.slugや
params.idと書かれていますが、
どこからその値が入ってくるのか、最初はよく分かりませんでした。
今回はURLとフォルダ構成を見比べながら、
paramsの役割を一つずつ整理します。
paramsという言葉が分からなかった
Next.jsとmicroCMSを使ったブログを勉強していると、
記事詳細ページのコードで
paramsという名前が出てきました。
export default async function Page({
params,
}: Props) {
const { slug } = await params;
return <p>{slug}</p>;
}
コードの形は何となく読めても、 最初は次の部分がよく分かりませんでした。
paramsは、どこから来たの?
自分で変数を作った覚えがありません。
なぜslugがparamsの中にあるのでしょうか。
URLと何か関係があるのでしょうか。
実際には、paramsはNext.jsがページへ渡してくれる値です。
そして、その中身は フォルダ名とURLの形によって決まります。
paramsとは何?
paramsは、
parameterを短くした名前としてよく使われます。
Next.jsのApp Routerでは、 URLの動的な部分をページ内で受け取るために使います。
ページごとに変わるURLの一部分を、 オブジェクトとしてまとめたものです。
例えば、ブログの記事詳細ページに 次のようなURLがあるとします。
https://example.com/blog/html-and-tsx
このURLの中で、
html-and-tsxの部分は
表示する記事によって変わります。
この動的部分をNext.jsが読み取り、 paramsの中へ入れてページに渡してくれます。
paramsは、URL全体ではなく、 角括弧で指定した動的な部分を受け取ります。
まずは固定URLを見てみる
動的ルーティングを理解する前に、 通常の固定ページを見てみます。
例えば、会社概要ページを
/aboutというURLで表示したい場合、
次のようなフォルダを作ります。
src
└── app
└── about
└── page.tsx
app/about/page.tsx
/about
aboutというフォルダ名が、
そのままURLの一部分になります。
このページは常に/aboutで表示されるため、
URLの一部が記事によって変わることはありません。
aboutフォルダなら/about、
contactフォルダなら/contactになります。
動的ルーティングとは?
ブログの記事詳細ページでは、 記事ごとにURLの最後が変わります。
/blog/html-and-tsx
/blog/nextjs-basic
/blog/microcms-start
これらの記事ごとに、 次のようなフォルダを一つずつ作ることもできます。
src
└── app
└── blog
├── html-and-tsx
│ └── page.tsx
├── nextjs-basic
│ └── page.tsx
└── microcms-start
└── page.tsx
しかし、記事が100件になれば、 100個のフォルダを作ることになります。
microCMSで記事を追加するたびに Next.js側へ新しいフォルダを作るのも現実的ではありません。
そこで使うのが、 動的ルーティングです。
src
└── app
└── blog
└── [slug]
└── page.tsx
[slug]というフォルダが、
さまざまな記事URLをまとめて受け取ります。
/blog/html-and-tsx
/blog/nextjs-basic
/blog/microcms-start
app/blog/[slug]/page.tsx
URLの一部がページごとに変わるときは、 フォルダ名を角括弧で囲みます。
[slug]とparamsの関係
それでは、
[slug]フォルダがどのようにparamsへつながるのか
見てみます。
app/blog/[slug]/page.tsx
/blog/html-and-tsx
{ slug: "html-and-tsx" }
角括弧の中にslugと書いたため、
paramsのプロパティ名もslugになります。
type Props = {
params: Promise<{
slug: string;
}>;
};
export default async function BlogPage({
params,
}: Props) {
const { slug } = await params;
return (
<main>
<h1>記事詳細ページ</h1>
<p>現在のslug:{slug}</p>
</main>
);
}
URLが/blog/html-and-tsxなら、
画面には次のように表示されます。
記事詳細ページ
現在のslug:html-and-tsx
[slug]の中へ入ったURLの値を、
params.slugとして受け取るイメージです。
[id]の場合はどうなる?
角括弧の中は、
必ずslugでなければいけないわけではありません。
商品詳細ページやmicroCMSのコンテンツIDを使う場合は、
[id]という名前もよく使われます。
src
└── app
└── products
└── [id]
└── page.tsx
[id]
/products/abc123
{ id: "abc123" }
type Props = {
params: Promise<{
id: string;
}>;
};
export default async function ProductPage({
params,
}: Props) {
const { id } = await params;
return (
<main>
<h1>商品詳細</h1>
<p>商品ID:{id}</p>
</main>
);
}
[slug]/blog/nextjs-basicparams.slug[id]/products/abc123params.id角括弧内の名前は自由に決められる
動的フォルダの名前は、 URLの値の意味が分かる名前を自分で決められます。
[slug]
記事やページの識別名
読みやすい文字列をURLに使う場合に向いています。
[id]
IDで識別
データベースやCMSのコンテンツIDを使う場合に向いています。
[category]
カテゴリ名
カテゴリごとの一覧ページなどに使えます。
[year]
年ごとのページ
年別アーカイブなどに使えます。
ただし、フォルダ名とparamsのプロパティ名は 必ず一致させます。
// フォルダは [id]
type Props = {
params: Promise<{
slug: string;
}>;
};
// フォルダは [id]
type Props = {
params: Promise<{
id: string;
}>;
};
フォルダが[id]なら
params.id、
フォルダが[slug]なら
params.slugです。
Next.js 16でのparamsの書き方
Next.js 16のApp Routerでは、 Server Componentへ渡されるparamsを Promiseとして受け取ります。
そのため、型にPromiseを付け、
await paramsで中身を取り出します。
現在の基本形
type Props = {
params: Promise<{
slug: string;
}>;
};
export default async function Page({
params,
}: Props) {
const { slug } = await params;
return <p>{slug}</p>;
}
Promise<...>
paramsがあとで解決される値であることを型で表します。
async
関数内でawaitを使えるようにします。
await params
Promiseを解決し、実際のURLの値を取得します。
以前の書籍や記事で見かける形
type Props = {
params: {
slug: string;
};
};
export default function Page({
params,
}: Props) {
return <p>{params.slug}</p>;
}
params.slug
const { slug } = await params
microCMSの記事詳細ページでparamsを使う
microCMSの記事詳細ページでは、 URLから取得したIDやslugを使って、 表示する記事を指定します。
microCMSから記事詳細を取得する関数
import { createClient } from "microcms-js-sdk";
export type Article = {
id: string;
title: string;
content: string;
};
const client = createClient({
serviceDomain:
process.env.MICROCMS_SERVICE_DOMAIN!,
apiKey:
process.env.MICROCMS_API_KEY!,
});
export const getArticleDetail = async (
contentId: string
) => {
return client.getListDetail<Article>({
endpoint: "blogs",
contentId,
});
};
paramsのidをmicroCMSへ渡す
import {
getArticleDetail,
} from "@/libs/microcms";
type Props = {
params: Promise<{
id: string;
}>;
};
export default async function ArticlePage({
params,
}: Props) {
const { id } = await params;
const article =
await getArticleDetail(id);
return (
<main>
<h1>{article.title}</h1>
<div
dangerouslySetInnerHTML={{
__html: article.content,
}}
/>
</main>
);
}
/blog/abc123
const { id } = await params
getArticleDetail(id)
titleやcontentをTSX内へ配置
paramsは記事データそのものではありません。 表示する記事をmicroCMSへ問い合わせるための IDやslugを受け取るものです。
複数階層を受け取るCatch-all Segment
通常の[slug]は、
URLの一つの階層だけを受け取ります。
app/blog/[slug]/page.tsx
→
/blog/nextjs
一方、ドキュメントサイトなどで、 複数階層のURLをまとめて受け取りたい場合があります。
/docs/nextjs
/docs/nextjs/routing
/docs/nextjs/routing/params
このような場合は、
角括弧の中へ...を付けた
Catch-all Segmentを使用できます。
src
└── app
└── docs
└── [...slug]
└── page.tsx
この場合、paramsのslugは文字列ではなく、 文字列の配列になります。
type Props = {
params: Promise<{
slug: string[];
}>;
};
export default async function DocsPage({
params,
}: Props) {
const { slug } = await params;
return (
<main>
<p>
{slug.join(" / ")}
</p>
</main>
);
}
/docs/nextjs
["nextjs"]
/docs/nextjs/routing
["nextjs", "routing"]
/docs/nextjs/routing/params
["nextjs", "routing", "params"]
初めてブログを作る段階では、
まず通常の[slug]や[id]を
理解できれば十分です。
paramsでよくあるつまずき
動的ルートにする場合は、
通常のslugではなく
[slug]とします。
app/blog/slug/page.tsx
→
app/blog/[slug]/page.tsx
[id]ならparams.id、
[slug]ならparams.slugです。
Next.js 16では、 Server ComponentのparamsをPromiseとして受け取ります。
const { slug } = await params;
awaitを使うページ関数には
asyncを付けます。
export default async function Page({
params,
}: Props) {
const { slug } = await params;
}
/blog/abc123で開く場合、
microCMSにabc123というIDの記事が
存在するか確認します。
URLのパス部分はparams、
?以降のクエリ文字列はsearchParamsです。
/blog/nextjs
/blog?keyword=nextjs
URLとparamsの関係をもう一度整理
ここまでの内容を、 ブログの記事詳細ページを例にしてまとめます。
角括弧の名前が paramsのプロパティ名になる
[slug]の位置へ html-and-tsxが入る
Next.js 16ではPromiseを awaitして受け取る
記事取得や画面表示に利用する
まとめ:paramsはURLの動的な値
paramsは、 Next.jsの動的ルーティングでURLの一部分を受け取るための値です。
最初はコードだけを見ると分かりにくいですが、 URLとフォルダ構成を一緒に見ると、 どこから値が来ているのか理解しやすくなります。
今回覚えておきたいこと
- paramsはURLの動的な部分を受け取る
-
動的なフォルダは
[slug]や[id]のように書く - 角括弧内の名前がparamsのプロパティ名になる
-
[slug]ならparams.slugとして受け取る -
[id]ならparams.idとして受け取る - Next.js 16ではparamsをPromiseとして受け取る
-
Server Componentでは
await paramsが必要 - microCMSではparamsのIDやslugを記事取得に使う
type Props = {
params: Promise<{
slug: string;
}>;
};
export default async function Page({
params,
}: Props) {
const { slug } = await params;
return (
<p>
現在のslug:{slug}
</p>
);
}
paramsは特別なデータを作る仕組みではなく、 URLに含まれている値を ページで利用できる形にしてくれるものです。
フォルダ名、URL、paramsの3つをつなげて考えることで、 記事詳細ページの仕組みが少しずつ見えるようになりました。
paramsとしてページへ渡されます。