Пошук уроків, статей та іншого контенту
Навчитеся використовувати сегменти [slug] для створення сторінок із динамічними параметрами маршруту.
У Next.js динамічний сегмент — це частина маршруту, значення якої визначається під час запиту.
Для створення динамічного сегмента використовується назва папки у квадратних дужках:
[slug]Наприклад:
app/
└── blog/
└── [slug]/
└── page.tsxТака структура створює маршрут:
/blog/<будь-яке-значення>Приклади URL:
/blog/nextjs-routing
/blog/server-components
/blog/learn-typescriptУ кожному випадку Next.js використовує один і той самий файл page.tsx, але передає йому різне значення параметра slug.
Створимо сторінку для статей блогу:
app/
├── blog/
│ └── [slug]/
│ └── page.tsx
└── page.tsxФайл app/blog/[slug]/page.tsx:
type BlogPageProps = {
params: Promise<{
slug: string;
}>;
};
export default async function BlogPage({ params }: BlogPageProps) {
const { slug } = await params;
return (
<main>
<h1>Стаття блогу</h1>
<p>Ідентифікатор статті: {slug}</p>
</main>
);
}Тепер перехід на адресу:
/blog/nextjs-routingпокаже:
Стаття блогу
Ідентифікатор статті: nextjs-routingА перехід на:
/blog/server-componentsпокаже:
Стаття блогу
Ідентифікатор статті: server-componentsparamsЗначення динамічних сегментів доступні у властивості params.
У сучасних версіях Next.js для серверної сторінки params має тип Promise, тому його потрібно отримати за допомогою await:
type PageProps = {
params: Promise<{
slug: string;
}>;
};
export default async function Page({ params }: PageProps) {
const { slug } = await params;
return <h1>{slug}</h1>;
}slug — назва параметра;
string — тип його значення;
await params — отримання об'єкта параметрів.
Назва властивості повинна збігатися з назвою папки. Для папки [slug] параметр буде називатися slug.
У реальному застосунку за значенням slug можна знайти потрібну статтю.
Створимо файл app/blog/[slug]/page.tsx:
type Article = {
slug: string;
title: string;
description: string;
};
const articles: Article[] = [
{
slug: "nextjs-routing",
title: "Маршрутизація в Next.js",
description: "Основи створення сторінок і маршрутів у Next.js.",
},
{
slug: "server-components",
title: "Серверні компоненти",
description: "Як працюють серверні компоненти в Next.js.",
},
{
slug: "typescript-basics",
title: "Основи TypeScript",
description: "Типи, інтерфейси та функції в TypeScript.",
},
];
type BlogPageProps = {
params: Promise<{
slug: string;
}>;
};
export default async function BlogPage({ params }: BlogPageProps) {
const { slug } = await params;
const article = articles.find((item) => item.slug === slug);
if (!article) {
return (
<main>
<h1>Статтю не знайдено</h1>
<p>Перевірте адресу сторінки.</p>
</main>
);
}
return (
<main>
<h1>{article.title}</h1>
<p>{article.description}</p>
<p>Slug статті: {article.slug}</p>
</main>
);
}Тепер маршрути працюватимуть так:
| URL | Результат | |---|---| | /blog/nextjs-routing | Сторінка про маршрутизацію | | /blog/server-components | Сторінка про серверні компоненти | | /blog/typescript-basics | Сторінка про TypeScript | | /blog/unknown-article | Повідомлення, що статтю не знайдено |
У прикладі масив articles використовується замість бази даних. У застосунку дані можуть надходити з API або іншого джерела.
Щоб перейти на динамічну сторінку, у посиланні потрібно вказати конкретне значення slug.
Наприклад, у файлі app/blog/page.tsx:
import Link from "next/link";
const articles = [
{
slug: "nextjs-routing",
title: "Маршрутизація в Next.js",
},
{
slug: "server-components",
title: "Серверні компоненти",
},
];
export default function BlogPage() {
return (
<main>
<h1>Блог</h1>
<ul>
{articles.map((article) => (
<li key={article.slug}>
<Link href={`/blog/${article.slug}`}>
{article.title}
</Link>
</li>
))}
</ul>
</main>
);
}Для першої статті Next.js сформує адресу:
/blog/nextjs-routingДля другої:
/blog/server-componentsШаблон:
<Link href={`/blog/${article.slug}`}>
{article.title}
</Link>вставляє значення slug у шлях маршруту.
Динамічний сегмент може бути частиною складнішого маршруту.
Наприклад:
app/
└── blog/
└── [slug]/
└── comments/
└── page.tsxЦе створює маршрути такого виду:
/blog/nextjs-routing/comments
/blog/server-components/commentsУ файлі page.tsx параметр усе одно буде доступний через params:
type CommentsPageProps = {
params: Promise<{
slug: string;
}>;
};
export default async function CommentsPage({
params,
}: CommentsPageProps) {
const { slug } = await params;
return (
<main>
<h1>Коментарі до статті</h1>
<p>Стаття: {slug}</p>
</main>
);
}Тут [slug] відповідає за назву статті, а comments є звичайним статичним сегментом.
Динамічний сегмент є частиною шляху URL:
/blog/nextjs-routingУ цьому URL:
blog — статичний сегмент;
nextjs-routing — значення динамічного сегмента [slug].
Значення slug не включає символи /. Наприклад, у маршруті:
/blog/nextjs-routingзначенням slug буде:
nextjs-routingПравильно:
app/blog/[slug]/page.tsxНеправильно:
app/blog/slug/page.tsxПапка slug без квадратних дужок створює лише статичний маршрут /blog/slug.
Для папки [slug] потрібно використовувати slug:
const { slug } = await params;Не слід очікувати параметр з іншою назвою:
const { id } = await params;Якщо потрібен параметр id, назвіть папку [id]:
app/blog/[id]/page.tsxawaitУ сучасних версіях Next.js параметри сторінки потрібно отримати асинхронно:
const { slug } = await params;Також сама функція сторінки має бути асинхронною:
export default async function Page({ params }: PageProps) {
// ...
}Маршрут потрібно перевіряти з різними значеннями:
/blog/first-article
/blog/second-article
/blog/unknown-articleСторінка має коректно працювати для існуючих і неіснуючих значень slug.
Динамічний сегмент створюється папкою з назвою у квадратних дужках, наприклад [slug].
Структура app/blog/[slug]/page.tsx відповідає маршрутам /blog/<значення>.
Значення сегмента доступне через властивість params.
У сучасних версіях Next.js params потрібно отримувати за допомогою await.
Значення slug можна використовувати для пошуку статті або іншого ресурсу.
Для посилання на динамічну сторінку потрібно вставити значення параметра в href.
Для невідомого значення параметра потрібно передбачити зрозумілу поведінку сторінки.