Menu
Coddy logo textTech

Динамические маршруты

Часть раздела Основы Next.js путешествия по React на Coddy — урок 8 из 47.

Меню с сорока блюдами не требует сорока папок. Вы хотите, чтобы /menu/pizza, /menu/pasta и /menu/tiramisu были одной и той же страницей, показывающей разные данные.

Вот что означают квадратные скобки в названии папки:

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

Обычная папка соответствует своему собственному имени. Папка [bracketed] соответствует любому сегменту и запоминает, с чем она совпала. Слово внутри скобок — это имя, по которому вы прочитаете это значение: [slug] дает вам slug, [id] дает вам id.

Next передаёт это значение странице в качестве пропа под названием params:

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

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

В этом небольшом файле происходят три вещи:

  • Страница принимает проп params. Каждая страница получает его, и для динамического маршрута он содержит совпавшие сегменты.
  • params — это Promise в Next 15, поэтому вы выполняете await для него. Вот почему компонент является async. В Главе 5 объясняется, почему страницам разрешено быть такими.
  • Деструктуризация извлекает slug, имя которого исходит напрямую из названия папки [slug].

Перейдите на /menu/pasta, и slug равен "pasta". Один файл, каждое блюдо.

challenge icon

Задание

Легко

Динамическая папка уже создана: app/menu/[slug]/page.jsx отвечает на каждый URL по адресу /menu. Проблема в том, что она показывает pizza независимо от того, какое блюдо вы запросили.

  1. Сделайте компонент async.
  2. Прочитайте совпавший сегмент с помощью const { slug } = await params;.
  3. Отобразите slug внутри <h1 id="dish"> вместо захардкоженного текста.

Тесты запрашивают два разных блюда и ожидают два разных заголовка.

Попробуйте сами

import './globals.css';

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

export default function RootLayout({ children }) {
    return (
        <html lang="en">
            <body>
                {children}
            </body>
        </html>
    );
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Основы Next.js