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
- /docs — params.slug === undefined
- /docs/getting-started — params.slug === ['getting-started']
- /docs/api/v1 — params.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.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ