/**
* Next.js 16 - Async Route Parameters
*
* BREAKING CHANGE: params, searchParams, cookies(), headers(), draftMode()
* are now async and must be awaited in Next.js 16.
*
* This template shows the correct patterns for accessing route parameters,
* search parameters, cookies, and headers in Next.js 16.
*/
import { cookies, headers, draftMode } from 'next/headers'
import { notFound } from 'next/navigation'
// ============================================================================
// Example 1: Page with Async Params
// ============================================================================
interface PageProps {
params: Promise<{ slug: string }>
searchParams: Promise<{ q?: string; page?: string }>
}
export default async function BlogPostPage({ params, searchParams }: PageProps) {
// ✅ Await params and searchParams in Next.js 16
const { slug } = await params
const { q, page } = await searchParams
// Fetch post data
const post = await fetch(`https://api.example.com/posts/${slug}`)
.then(r => r.json())
.catch(() => null)
if (!post) {
notFound()
}
return (
{post.title}
{/* Show search query if present */}
{q && Search query: {q}
}
{/* Show page number if present */}
{page && Page: {page}
}
)
}
// ============================================================================
// Example 2: Layout with Async Params
// ============================================================================
interface LayoutProps {
children: React.ReactNode
params: Promise<{ category: string }>
}
export async function ProductLayout({ children, params }: LayoutProps) {
// ✅ Await params in layouts too
const { category } = await params
return (
{children}
)
}
// ============================================================================
// Example 3: Accessing Cookies (Async in Next.js 16)
// ============================================================================
export async function UserGreeting() {
// ✅ Await cookies() in Next.js 16
const cookieStore = await cookies()
const userId = cookieStore.get('userId')?.value
const theme = cookieStore.get('theme')?.value || 'light'
if (!userId) {
return Welcome, Guest!
}
const user = await fetch(`https://api.example.com/users/${userId}`)
.then(r => r.json())
return (
Welcome back, {user.name}!
)
}
// ============================================================================
// Example 4: Accessing Headers (Async in Next.js 16)
// ============================================================================
export async function RequestInfo() {
// ✅ Await headers() in Next.js 16
const headersList = await headers()
const userAgent = headersList.get('user-agent') || 'Unknown'
const referer = headersList.get('referer') || 'Direct'
const ip = headersList.get('x-forwarded-for') || 'Unknown'
return (
User Agent: {userAgent}
Referrer: {referer}
IP: {ip}
)
}
// ============================================================================
// Example 5: Draft Mode (Async in Next.js 16)
// ============================================================================
export async function DraftBanner() {
// ✅ Await draftMode() in Next.js 16
const { isEnabled } = await draftMode()
if (!isEnabled) {
return null
}
return (
)
}
// ============================================================================
// Example 6: Generate Metadata with Async Params
// ============================================================================
import type { Metadata } from 'next'
export async function generateMetadata({ params }: PageProps): Promise {
// ✅ Await params in generateMetadata
const { slug } = await params
const post = await fetch(`https://api.example.com/posts/${slug}`)
.then(r => r.json())
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
images: [post.coverImage],
},
}
}
// ============================================================================
// Example 7: Generate Static Params (Async)
// ============================================================================
export async function generateStaticParams() {
const posts = await fetch('https://api.example.com/posts')
.then(r => r.json())
return posts.map((post: { slug: string }) => ({
slug: post.slug,
}))
}
// ============================================================================
// Example 8: Route Handler with Async Params
// ============================================================================
// File: app/api/posts/[id]/route.ts
import { NextResponse } from 'next/server'
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
// ✅ Await params in route handlers
const { id } = await params
const post = await fetch(`https://api.example.com/posts/${id}`)
.then(r => r.json())
return NextResponse.json(post)
}
export async function DELETE(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
// ✅ Await params in route handlers
const { id } = await params
await fetch(`https://api.example.com/posts/${id}`, {
method: 'DELETE',
})
return NextResponse.json({ message: 'Post deleted' })
}
// ============================================================================
// Migration Guide: Next.js 15 → Next.js 16
// ============================================================================
// ❌ BEFORE (Next.js 15):
/*
export default function Page({ params, searchParams }) {
const slug = params.slug // ❌ Sync access
const query = searchParams.q // ❌ Sync access
}
export function MyComponent() {
const cookieStore = cookies() // ❌ Sync access
const headersList = headers() // ❌ Sync access
}
*/
// ✅ AFTER (Next.js 16):
/*
export default async function Page({ params, searchParams }) {
const { slug } = await params // ✅ Async access
const { q: query } = await searchParams // ✅ Async access
}
export async function MyComponent() {
const cookieStore = await cookies() // ✅ Async access
const headersList = await headers() // ✅ Async access
}
*/
// ============================================================================
// TypeScript Types
// ============================================================================
// Correct types for Next.js 16:
type Params> = Promise
type SearchParams = Promise<{ [key: string]: string | string[] | undefined }>
// Usage:
type ProductPageProps = {
params: Params<{ id: string }>
searchParams: SearchParams
}
// ============================================================================
// Codemod (Automatic Migration)
// ============================================================================
// Run this command to automatically migrate your code:
// npx @next/codemod@canary upgrade latest
/**
* Summary:
*
* 1. ALL route parameters are now async:
* - params → await params
* - searchParams → await searchParams
*
* 2. ALL next/headers functions are now async:
* - cookies() → await cookies()
* - headers() → await headers()
* - draftMode() → await draftMode()
*
* 3. Components using these must be async:
* - export default async function Page({ params }) { ... }
* - export async function Layout({ params }) { ... }
* - export async function generateMetadata({ params }) { ... }
*
* 4. Route handlers must await params:
* - export async function GET(request, { params }) {
* const { id } = await params
* }
*/