Await request APIs
In Next.js 15, params, cookies() and headers() are Promises.
From next-best-practices, async-patterns.md.
Type it, run it
Edit the lines; try deleting await on the right.
Read like an objectBad
export default async function Page({ params }) {
return <h1 className={theme}>{slug}</h1>
}
AwaitedGood
export default async function Page({ params }) {
return <h1 className={theme}>{slug}</h1>
}
// app/blog/[slug]/page.tsx
import { cookies } from 'next/headers'
type Props = {
params: Promise<{ slug: string }>
searchParams: Promise<{ query?: string }>
}
export default async function Page({ params, searchParams }: Props) {
const { slug } = await params
const { query } = await searchParams
const theme = (await cookies()).get('theme')?.value
return <h1 className={theme}>{slug}</h1>
}
Sync component: use(params)
Click a cell to switch component and unwrap.
page.tsxServer
Renders
/blog/| Component | params | await | use() |
|---|
import { use } from 'react'
type Props = { params: Promise<{ slug: string }> }
export default function Page({ params }: Props) {
const { slug } = use(params)
return <h1>{slug}</h1>
}
Run the codemod
Run it, then switch views.
app/blog/[slug]/page.tsxWhy it matters, pros and cons
Why it matters
Request data exists per request, so Next.js hands it over as a Promise.
Pros
- A sync read becomes a type error.
- One pattern for pages, layouts and handlers.
- A codemod does most of the migration.
Cons
await params.slugawaits undefined; write(await params).slug.- Sync components can't
await; useuse(). - Reading
cookies()orheaders()makes the render dynamic.