Menu
Coddy logo textTech

Dynamic Routes

Part of the Next.js Essentials section of Coddy's React journey — lesson 8 of 47.

A menu with forty dishes doesn't get forty folders. You want /menu/pizza, /menu/pasta and /menu/tiramisu to be the same page showing different data.

That's what square brackets in a folder name mean:

app/
    menu/
        [slug]/
            page.jsx     ->  /menu/pizza
                         ->  /menu/pasta
                         ->  /menu/anything-at-all

A normal folder matches its own name. A [bracketed] folder matches any segment and remembers what it matched. The word inside the brackets is the name you'll read it back by: [slug] gives you slug, [id] gives you id.

Next hands that value to the page as a prop called params:

// app/menu/[slug]/page.jsx
export default async function Dish({ params }) {
    const { slug } = await params;

    return <h1>{slug}</h1>;
}

Three things happen in that tiny file:

  • The page takes a params prop. Every page gets one, and for a dynamic route it holds the matched segments.
  • params is a Promise in Next 15, so you await it. That's why the component is async. Chapter 5 explains why pages are allowed to be.
  • Destructuring pulls out slug, whose name comes straight from the folder [slug].

Visit /menu/pasta and slug is "pasta". One file, every dish.

challenge icon

Challenge

Easy

The dynamic folder is already there: app/menu/[slug]/page.jsx answers every URL under /menu. Trouble is, it says pizza no matter which dish you asked for.

  1. Make the component async.
  2. Read the matched segment with const { slug } = await params;.
  3. Render slug inside the <h1 id="dish"> instead of the hardcoded text.

The tests visit two different dishes and expect two different headings.

Try it yourself

import './globals.css';

export const metadata = {
    title: 'My App',
};

export default function RootLayout({ children }) {
    return (
        <html lang="en">
            <body>
                {children}
            </body>
        </html>
    );
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Next.js Essentials