JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Создание различных типов маршрутов, вложенность (Next.js ...

Создание различных типов маршрутов, вложенность (Next.js 15, App Router)

Модуль 4: Node.js, Next.js и Angular
8 уровень , 3 лекция
Открыта

1. Динамические маршруты: [param] и как их использовать

Маршрутизация — это не просто «страницы по папкам». В реальных приложениях нам часто нужны:

  • Динамические страницы (например, /products/123, где 123 — id товара)
  • Опциональные сегменты (например, /blog/2024 и просто /blog)
  • Вложенные маршруты (например, /dashboard/settings/profile)
  • Глубокие вложения (например, /users/42/posts/7/comments/3)

App Router в Next.js 15 позволяет строить такие маршруты очень гибко, просто организуя папки и файлы.

Синтаксис

Чтобы создать динамический маршрут, используйте квадратные скобки в названии папки или файла:


app/
  products/
    [id]/
      page.tsx

Это создаст маршрут /products/:id, где id — переменная.

Пример: Страница товара


// app/products/[id]/page.tsx
import { useParams } from 'next/navigation';

export default function ProductPage({ params }: { params: { id: string } }) {
  return (
    <div>
      <h1>Товар № {params.id}</h1>
      <p>Здесь могла быть ваша реклама!</p>
    </div>
  );
}

Факт: В Server Components параметры передаются через пропс params, а в Client Components — через хук useParams.

Как это работает

  • URL /products/123 отобразит страницу с params.id === '123'.
  • URL /products/abc — с params.id === 'abc'.

Несколько динамических сегментов

Можно делать и так:


app/
  users/
    [userId]/
      posts/
        [postId]/
          page.tsx

URL /users/42/posts/7 попадёт на этот маршрут, где params.userId === '42', params.postId === '7'.

2. Опциональные и «catch-all» сегменты: [...slug], [[...slug]]

Catch-all маршруты: [...slug]

Если вы хотите поймать все вложенные пути, используйте три точки:


app/
  blog/
    [...slug]/
      page.tsx

Пояснение:

  • /blog — попадёт сюда (params.slug === [])
  • /blog/2024 — (params.slug === ['2024'])
  • /blog/2024/04/01 — (params.slug === ['2024','04','01'])

Это удобно для страниц с произвольной глубиной вложенности, например, для блога с древовидной структурой.

Опциональные catch-all: [[...slug]]

Если маршрут может быть и без параметров, и с ними, используйте двойные скобки:


app/
  docs/
    [[...slug]]/
      page.tsx
  • /docsparams.slug === undefined
  • /docs/getting-startedparams.slug === ['getting-started']
  • /docs/api/v1params.slug === ['api','v1']

Пример:


// app/docs/[[...slug]]/page.tsx
export default function DocsPage({ params }: { params: { slug?: string[] } }) {
  return (
    <div>
      <h1>Документация</h1>
      <pre>{JSON.stringify(params.slug)}</pre>
    </div>
  );
}

3. Вложенные маршруты: структура папок = структура URL

В Next.js 15 App Router вложенность маршрутов определяется папками. Каждый уровень вложенности — это новая папка.

Пример: Панель управления


app/
  dashboard/
    page.tsx          // /dashboard
    settings/
      page.tsx        // /dashboard/settings
      profile/
        page.tsx      // /dashboard/settings/profile
  • /dashboard — главная страница панели
  • /dashboard/settings — настройки
  • /dashboard/settings/profile — профиль

Всё очень просто: структура папок = структура URL.

Как это выглядит в коде


// app/dashboard/settings/profile/page.tsx
export default function ProfileSettings() {
  return <h2>Настройки профиля</h2>;
}

4. Комбинирование вложенности и динамики

Можно совмещать динамические сегменты и вложенность:


app/
  users/
    [userId]/
      page.tsx           // /users/42
      posts/
        [postId]/
          page.tsx       // /users/42/posts/7

В коде вы получите оба параметра:


// app/users/[userId]/posts/[postId]/page.tsx
export default function UserPost({ params }: { params: { userId: string, postId: string } }) {
  return <div>Пост {params.postId} пользователя {params.userId}</div>;
}

5. Пример: ваше приложение для задач

Допустим, у вас есть приложение для задач (todo). Мы хотим:

  • /tasks — список всех задач
  • /tasks/[id] — страница детали задачи
  • /tasks/[id]/edit — страница редактирования задачи

Структура будет такой:


app/
  tasks/
    page.tsx           // /tasks
    [id]/
      page.tsx         // /tasks/123
      edit/
        page.tsx       // /tasks/123/edit

Пример кода для страницы задачи:


// app/tasks/[id]/page.tsx
export default function TaskDetail({ params }: { params: { id: string } }) {
  return <div>Детали задачи №{params.id}</div>;
}

Пример кода для редактирования:


// app/tasks/[id]/edit/page.tsx
export default function EditTask({ params }: { params: { id: string } }) {
  return <div>Редактирование задачи №{params.id}</div>;
}

6. Вложенность и layout.tsx: общий макет для группы маршрутов

В App Router можно использовать файл layout.tsx в любой папке. Он определяет внешний вид (шапка, меню, футер и т.д.) для всех вложенных маршрутов.

Пример:


app/
  dashboard/
    layout.tsx
    page.tsx
    settings/
      page.tsx

layout.tsx будет применяться и к /dashboard, и к /dashboard/settings.

Код:


// app/dashboard/layout.tsx
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
  return (
    <div>
      <aside>Меню панели</aside>
      <main>{children}</main>
    </div>
  );
}

7. Вложенные маршруты и навигация: Link и usePathname

Для перехода между вложенными маршрутами используйте компонент Link из next/link:


import Link from 'next/link';

<Link href="/dashboard/settings">Настройки</Link>

Для получения текущего пути используйте хук usePathname:


import { usePathname } from 'next/navigation';

const pathname = usePathname();

8. Вложенные маршруты: типичные ошибки и нюансы

Ошибка №1: Опечатка в имени папки или файла.
Next.js чувствителен к регистру и точному написанию. Если назовёте папку [Id] вместо [id], маршрут не сработает.

Ошибка №2: Несовпадение структуры папок и желаемого URL.
Если хотите /blog/2024/04/01, структура папок должна быть blog/2024/04/01/page.tsx или использовать catch-all.

Ошибка №3: Параметры не приходят в компонент.
Проверьте, что имя папки/файла в скобках совпадает с используемым в пропсе params. Не забудьте, что для catch-all это массив.

Ошибка №4: Не тот layout применяется.
layout.tsx применяется на уровне своей папки и всех вложенных. Если layout не работает, проверьте, где он лежит и нет ли конфликтов.

Ошибка №5: Попытка использовать useParams в Server Component.
В Server Component параметры приходят через пропс params, а хук useParams работает только в Client Component.

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ