Пошук уроків, статей та іншого контенту
Застосуєте Route Groups для логічної організації файлів без додавання сегментів до URL.
Route Groups — це папки в app, назви яких записані в круглих дужках:
app/
├── (marketing)/
├── (dashboard)/
└── layout.tsxТакі папки використовуються лише для організації файлів. Їхні назви не додаються до URL.
Наприклад:
app/
└── (marketing)/
└── about/
└── page.tsxСторінка буде доступна за адресою:
/aboutа не:
/(marketing)/aboutRoute Groups допомагають:
розділяти сторінки за призначенням;
групувати маршрути для різних частин застосунку;
застосовувати окремий layout до певної групи;
організовувати великі проєкти без зміни публічних URL.
Наприклад, сторінки маркетингової частини та панелі керування можна зберігати окремо:
app/
├── (marketing)/
│ ├── layout.tsx
│ ├── page.tsx
│ └── pricing/
│ └── page.tsx
├── (dashboard)/
│ ├── layout.tsx
│ └── settings/
│ └── page.tsx
└── layout.tsxЦі файли відповідають таким URL:
app/(marketing)/page.tsx
→ /
app/(marketing)/pricing/page.tsx
→ /pricing
app/(dashboard)/settings/page.tsx
→ /settingsНазви (marketing) і (dashboard) не є частиною адрес.
Розглянемо структуру застосунку:
app/
├── (public)/
│ ├── about/
│ │ └── page.tsx
│ └── pricing/
│ └── page.tsx
├── (account)/
│ ├── profile/
│ │ └── page.tsx
│ └── orders/
│ └── page.tsx
└── layout.tsx// app/(public)/about/page.tsx
export default function AboutPage() {
return (
<main>
<h1>Про компанію</h1>
<p>Це публічна сторінка застосунку.</p>
</main>
);
}Сторінка відкривається за адресою /about.
// app/(account)/profile/page.tsx
export default function ProfilePage() {
return (
<main>
<h1>Профіль користувача</h1>
<p>Тут користувач може переглянути свої дані.</p>
</main>
);
}Сторінка відкривається за адресою /profile.
Папки (public) і (account) логічно розділяють файли, але не впливають на маршрути.
Route Group може містити власний layout.tsx. Цей layout застосовується до сторінок усередині групи.
Структура:
app/
├── (public)/
│ ├── layout.tsx
│ ├── about/
│ │ └── page.tsx
│ └── pricing/
│ └── page.tsx
├── (account)/
│ ├── layout.tsx
│ └── profile/
│ └── page.tsx
└── layout.tsxLayout групи (public) може містити навігацію публічної частини:
// app/(public)/layout.tsx
import Link from "next/link";
import type { ReactNode } from "react";
type PublicLayoutProps = {
children: ReactNode;
};
export default function PublicLayout({
children,
}: PublicLayoutProps) {
return (
<>
<header>
<nav>
<Link href="/about">Про компанію</Link>{" "}
<Link href="/pricing">Тарифи</Link>
</nav>
</header>
{children}
</>
);
}Сторінки about і pricing отримають цей layout:
/about
/pricingАле сторінка з групи (account) його не отримає:
/profileВона може мати власний layout:
// app/(account)/layout.tsx
import type { ReactNode } from "react";
type AccountLayoutProps = {
children: ReactNode;
};
export default function AccountLayout({
children,
}: AccountLayoutProps) {
return (
<section>
<aside>
<p>Меню облікового запису</p>
</aside>
<div>{children}</div>
</section>
);
}У результаті різні частини застосунку можуть мати різну структуру, хоча їхні маршрути залишаються короткими та зрозумілими.
Layout у Route Group не замінює кореневий layout. Він вкладається в layout батьківських рівнів.
Наприклад:
app/
├── layout.tsx
└── (account)/
├── layout.tsx
└── profile/
└── page.tsxДля /profile порядок вкладеності буде таким:
app/layout.tsx
└── app/(account)/layout.tsx
└── app/(account)/profile/page.tsxТому кореневий app/layout.tsx зазвичай містить спільну для всього застосунку структуру:
// app/layout.tsx
import type { ReactNode } from "react";
type RootLayoutProps = {
children: ReactNode;
};
export default function RootLayout({
children,
}: RootLayoutProps) {
return (
<html lang="uk">
<body>{children}</body>
</html>
);
}А layout Route Group додає структуру лише для своєї частини.
Один із практичних варіантів — створити групи для різних розділів застосунку:
app/
├── (site)/
│ ├── layout.tsx
│ ├── page.tsx
│ ├── about/
│ │ └── page.tsx
│ └── contact/
│ └── page.tsx
├── (dashboard)/
│ ├── layout.tsx
│ ├── dashboard/
│ │ └── page.tsx
│ └── reports/
│ └── page.tsx
└── layout.tsxURL будуть такими:
/
/about
/contact
/dashboard
/reportsПри цьому:
сторінки з (site) можуть використовувати layout публічного сайту;
сторінки з (dashboard) можуть використовувати layout панелі керування;
URL не містять технічних назв груп.
Назва групи має описувати логічне призначення файлів. Наприклад:
(marketing)
(auth)
(dashboard)
(shop)Route Groups можна вкладати один в одного, якщо це допомагає організувати складну структуру:
app/
└── (dashboard)/
├── (admin)/
│ └── users/
│ └── page.tsx
└── (support)/
└── tickets/
└── page.tsxУ цьому випадку маршрути будуть:
/users
/ticketsУсі назви в дужках виключаються з URL.
Вкладені групи варто використовувати лише тоді, коли вони справді спрощують структуру проєкту. Надмірна кількість рівнів може ускладнити пошук файлів.
Route Groups не створюють окремий сегмент URL. Через це дві різні групи не можуть містити сторінки з однаковим кінцевим маршрутом.
Неприпустима структура:
app/
├── (public)/
│ └── settings/
│ └── page.tsx
└── (account)/
└── settings/
└── page.tsxОбидві сторінки відповідають одному URL:
/settingsNext.js не зможе однозначно визначити, яку сторінку використовувати.
Потрібно змінити URL або структуру файлів, наприклад:
app/
├── (public)/
│ └── public-settings/
│ └── page.tsx
└── (account)/
└── settings/
└── page.tsxТепер маршрути не конфліктують:
/public-settings
/settingsapp/
├── layout.tsx
├── (marketing)/
│ ├── layout.tsx
│ ├── page.tsx
│ └── pricing/
│ └── page.tsx
└── (dashboard)/
├── layout.tsx
├── dashboard/
│ └── page.tsx
└── reports/
└── page.tsxКореневий layout:
// app/layout.tsx
import type { ReactNode } from "react";
type RootLayoutProps = {
children: ReactNode;
};
export default function RootLayout({
children,
}: RootLayoutProps) {
return (
<html lang="uk">
<body>{children}</body>
</html>
);
}Layout маркетингової частини:
// app/(marketing)/layout.tsx
import Link from "next/link";
import type { ReactNode } from "react";
type MarketingLayoutProps = {
children: ReactNode;
};
export default function MarketingLayout({
children,
}: MarketingLayoutProps) {
return (
<>
<header>
<strong>Мій продукт</strong>
<nav>
<Link href="/">Головна</Link>{" "}
<Link href="/pricing">Тарифи</Link>
</nav>
</header>
{children}
</>
);
}Layout панелі керування:
// app/(dashboard)/layout.tsx
import Link from "next/link";
import type { ReactNode } from "react";
type DashboardLayoutProps = {
children: ReactNode;
};
export default function DashboardLayout({
children,
}: DashboardLayoutProps) {
return (
<div>
<aside>
<nav>
<Link href="/dashboard">Панель</Link>{" "}
<Link href="/reports">Звіти</Link>
</nav>
</aside>
<main>{children}</main>
</div>
);
}Сторінка тарифів:
// app/(marketing)/pricing/page.tsx
export default function PricingPage() {
return (
<main>
<h1>Тарифи</h1>
<p>Оберіть план для свого проєкту.</p>
</main>
);
}Сторінка звітів:
// app/(dashboard)/reports/page.tsx
export default function ReportsPage() {
return (
<main>
<h1>Звіти</h1>
<p>Тут відображаються звіти користувача.</p>
</main>
);
}У цьому прикладі:
/pricing використовує app/(marketing)/layout.tsx;
/reports використовує app/(dashboard)/layout.tsx;
жодна URL-адреса не містить (marketing) або (dashboard);
обидві сторінки також успадковують app/layout.tsx.
app/(shop)/products/page.tsxЦе маршрут /products, а не /shop/products.
Якщо сегмент має бути частиною URL, не використовуйте круглі дужки:
app/shop/products/page.tsxТоді маршрут буде /shop/products.
Не створюйте однаковий шлях у двох групах:
app/(one)/profile/page.tsx
app/(two)/profile/page.tsxОбидва файли відповідають /profile і спричинять конфлікт.
Layout із app/(marketing)/layout.tsx застосовується лише до маршрутів усередині (marketing). Він не впливає на сторінки з (dashboard).
Якщо елемент потрібен усім сторінкам, розмістіть його в батьківському або кореневому layout.
Назва (group1) не пояснює призначення папки. Краще використовувати назви, які відображають роль групи:
(marketing)
(account)
(dashboard)Route Group — це папка з назвою в круглих дужках, наприклад (dashboard).
Назва Route Group не потрапляє до URL.
Route Groups використовуються для логічної організації файлів.
Група може мати власний layout.tsx.
Layout групи застосовується до всіх сторінок усередині цієї групи.
Різні групи можуть мати різні layout.
Не можна створювати однаковий URL у двох Route Groups.
Якщо сегмент має бути в URL, його потрібно створити як звичайну папку без круглих дужок.