100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
JavaScript

Dynamic Routes and Params

Understand how to build dynamic and catch-all routes using bracket folder naming, read route params in Server and Client Components, and pre-render them with generateStaticParams.

Navigation & UIIntermediate9 min readJul 10, 2026
Analogies

Dynamic Segments with Square Brackets

Next.js's App Router creates dynamic route segments by wrapping a folder name in square brackets, such as app/blog/[slug]/page.tsx, which matches any URL like /blog/hello-world or /blog/nextjs-tips. The bracketed name becomes the key in a params object that Next.js passes to the page component, so a request to /blog/hello-world resolves params.slug to the string 'hello-world'. This convention lets a single page component serve an unbounded number of URLs, which is essential for content-driven sites like blogs, e-commerce product pages, or user profiles where the total number of pages isn't known at build time.

🏏

Cricket analogy: A dynamic segment like [playerId] is like a scoreboard template that plugs in any player's name and stats, the same physical board serving every player without a custom board built for each one.

Catch-all and Optional Catch-all Routes

Beyond single dynamic segments, Next.js supports catch-all routes using [...slug], which matches any number of path segments after a given point and delivers them as an array, so /docs/a/b/c would produce params.slug = ['a', 'b', 'c']. An optional catch-all route uses double brackets, [[...slug]], which additionally matches the base path itself with no extra segments at all, making params.slug undefined for /docs while still matching /docs/a/b. This pattern is common for documentation sites or CMS-driven pages where content lives in a nested tree of arbitrary depth.

🏏

Cricket analogy: A catch-all route is like a wicketkeeper positioned to collect any number of byes down the leg side, regardless of how many runs are attempted, one fielder covering a whole range of outcomes.

Accessing Params in Server and Client Components

In a Server Component page, params is available as a prop passed directly to the default export; as of Next.js 15, params is a Promise that must be awaited, a change from Next.js 14 and earlier where it was a plain object, so upgrading requires updating page signatures to async functions. In Client Components, you can't receive params as a prop the same way, so you instead call the useParams hook from next/navigation, which reads the current route's dynamic segments and returns them synchronously as an object, working identically for both single and catch-all segments.

🏏

Cricket analogy: Awaiting params in Next.js 15 is like waiting for the third umpire's review to come back before the scoreboard updates, whereas the old synchronous style was like the on-field umpire's instant, no-review call.

tsx
// app/blog/[slug]/page.tsx (Next.js 15 Server Component)
type Props = { params: Promise<{ slug: string }> };

export default async function BlogPost({ params }: Props) {
  const { slug } = await params;
  const post = await getPostBySlug(slug);
  return <article><h1>{post.title}</h1><p>{post.body}</p></article>;
}

// app/blog/[slug]/ShareButton.tsx (Client Component)
'use client';
import { useParams } from 'next/navigation';

export function ShareButton() {
  const params = useParams<{ slug: string }>();
  return <button onClick={() => navigator.share({ url: `/blog/${params.slug}` })}>Share</button>;
}

generateStaticParams for Static Generation

For dynamic routes you want pre-rendered at build time instead of on every request, you export a generateStaticParams function from the page file that returns an array of param objects, one per page Next.js should statically generate, such as [{ slug: 'hello-world' }, { slug: 'nextjs-tips' }]. Any path not included in that array falls back to dynamic rendering at request time by default, unless dynamicParams is explicitly set to false, in which case unmatched paths return a 404. This is the App Router's equivalent of getStaticPaths from the pages router, and combining it with fetch's built-in caching lets you build a fully static blog that still deploys new posts without a full redeploy when dynamicParams remains true.

🏏

Cricket analogy: generateStaticParams is like printing scorecards in advance for every confirmed match in a tournament schedule, so fans get them instantly, while a late-added exhibition match gets a hand-written card printed on the spot.

generateStaticParams can be combined with a parent layout's params: pages nested several dynamic segments deep (e.g. app/[category]/[product]/page.tsx) can call the parent's params inside their own generateStaticParams to generate only valid combinations, avoiding a full cartesian product of every category with every product.

In Next.js 15, params (and searchParams) became Promises in both page and layout Server Components as part of enabling partial prerendering. If you upgrade from Next.js 14, code that destructures params synchronously will throw a type error or return a Promise object instead of the expected values — you must await it or use the React use() hook.

  • Square-bracket folders like [slug] create dynamic route segments matched into a params object.
  • [...slug] creates a catch-all route capturing an array of segments; [[...slug]] makes it optional, also matching the base path.
  • In Next.js 15, params is a Promise in Server Components and must be awaited inside an async page function.
  • useParams from next/navigation reads dynamic segments synchronously inside Client Components.
  • generateStaticParams pre-renders specific dynamic paths at build time, similar to getStaticPaths in the pages router.
  • Paths not returned by generateStaticParams render dynamically at request time unless dynamicParams is set to false.
  • Nested dynamic segments can use parent params inside generateStaticParams to avoid generating invalid combinations.

Practice what you learned

Was this page helpful?

Topics covered

#JavaScript#NextJsStudyNotes#WebDevelopment#DynamicRoutesAndParams#Dynamic#Routes#Params#Segments#StudyNotes#SkillVeris