params が undefined になる原因と直し方
実際に出るエラー
Next.js 16 では params が Promise として渡されるので、await せずに読むと中身が undefined になります。
本番では何も言われない
古い記事にある書き方を、そのまま Next.js 16 で動かしました。
export default function Page({ params }: { params: { slug: string } }) {
return <p>{`slug=${params.slug}`}</p>
}
| 開発(next dev) | 本番(next build → start) | |
|---|---|---|
| 型チェック | — | 通る |
| ページ | 出る。slug=undefined | 出る。slug=undefined |
| 文言 | ログに出る | どこにも出ない |
本番では、型チェックもビルドも通り、ログにも何も残りません。中身が undefined のページが、黙って出ます。
文言が出るのは開発サーバーのログだけです。params を読んだ行を指して、上の文言が出ます。
なぜ undefined になるのか
Next.js 16 では、params は Promise として渡されます。Promise に slug という項目は無いので、そのまま読むと undefined です。
公式のアップグレードガイドによると、Next.js 15 では一時的に同期のままでも読めましたが、16 でその読み方はなくなりました。検索して見つかる例の多くはその頃の書き方なので、写すとこうなります。
直し方
Server Component(ふつうのページ)
ページを async にして、await で取り出します。型も Promise と書きます。
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
return <p>{`slug=${slug}`}</p>
}
実機で、/hello に「slug=hello」が入ることを確かめました。
Client Component
'use client' のページでは async にできないので、React の use で取り出します。文言が言っている React.use() はこれです。
'use client'
import { use } from 'react'
export default function Page({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = use(params)
return <p>{`slug=${slug}`}</p>
}
実機で、/abc を開くと「slug=abc」と出ることを確かめました。
params だけではない
同じく Promise で渡されるものがあります。どれも await して取り出します。
searchParams(ページに渡るクエリ文字列)generateMetadataに渡るparams
Next.js が生成するページの型(PageProps)でも、params と searchParams は Promise になっています。
直したあとに確かめること
- 開発サーバーで一度開く。読み忘れがあれば、ログに上の文言が出ます
- 画面に
undefinedが出ていないかを、動的なページごとに見る generateMetadataの中のparamsも見直す。title が undefined になっていても気づきにくい
出典
- nextjs.org/docs/messages/sync-dynamic-apis
- nextjs.org/docs/app/api-reference/file-conventions/page
- nextjs.org/docs/app/guides/upgrading/version-16
このページの内容は上記の一次情報を基準に書いています。個人ブログや二次情報を根拠にしていません。