C.W.K.
Stream
Lesson 02 of 10 · published

page.tsx — The Route Component

~22 min · page, params, Promise

Level 0Curious
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

The shape of a page

A page.tsx exports a default React component. By default it's a Server Component, so it can be async. Server Components don't take many props — the framework injects route data via two specific props:

  • params: route parameters from [slug]-style segments.
  • searchParams: query string parameters from the URL.

Both props are Promises in v15+

The big breaking change from v14 to v15: params and searchParams are Promises. You must await them. In Client Components, use React.use(params). The Promise wrap unblocks parallel rendering — nothing has to wait for params resolution before it starts.

Type helpers

Next.js publishes typed helpers under the next module entry. PageProps<'/blog/[slug]'> gives you a fully typed params based on the literal route path.

Code

Async page with awaited params·tsx
// app/blog/[slug]/page.tsx
type Props = {
  params: Promise<{ slug: string }>;
  searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
};

export default async function BlogPost({ params, searchParams }: Props) {
  const { slug } = await params;
  const { sort = 'newest' } = await searchParams;
  const post = await fetchPost(slug, { sort });

  return (
    <article>
      <h1>{post.title}</h1>
      <p className="text-sm text-gray-500">sort: {sort}</p>
      <div dangerouslySetInnerHTML={{ __html: post.html }} />
    </article>
  );
}
Typed via PageProps·tsx
import type { PageProps } from 'next';

export default async function Page({ params }: PageProps<'/blog/[slug]'>) {
  const { slug } = await params; // typed: { slug: string }
  return <Article slug={slug} />;
}
Client Component variant·tsx
'use client';
import { use } from 'react';

export default function ClientPage({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = use(params); // React.use unwraps the Promise
  return <div>Slug: {slug}</div>;
}

External links

Exercise

Pick one of your existing pages with params and searchParams. Convert it to await both, type it with PageProps, and verify nothing regresses.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.