Пошук уроків, статей та іншого контенту
Створите маршрути з динамічними сегментами для сторінок, URL яких залежать від ідентифікатора або іншого значення.
Динамічний маршрут — це маршрут, частина якого змінюється залежно від значення в URL.
Наприклад, сторінки товарів можуть мати такі адреси:
/products/1
/products/2
/products/15Замість створення окремого маршруту для кожного товару можна описати один маршрут:
/products/:productIdproductId називається параметром маршруту. На його місці в URL буде конкретне значення, наприклад 1 або 15.
Для роботи з маршрутами використовуйте пакет react-router-dom:
npm install react-router-domПараметр маршруту позначається двокрапкою:
<Route path="/products/:productId" element={<ProductPage />} />У цьому прикладі:
/products/ — статична частина маршруту;
:productId — динамічний сегмент;
ProductPage — компонент, який відобразиться для такого маршруту.
Маршрут буде відповідати URL:
/products/1
/products/25
/products/abcЗначення параметра можна отримати за допомогою хука useParams.
useParamsuseParams повертає об’єкт із параметрами поточного маршруту.
const params = useParams();
console.log(params.productId);Або можна одразу деструктуризувати потрібний параметр:
const { productId } = useParams();Важливо: усі параметри маршруту повертаються як рядки. Навіть якщо URL містить число 15, значення productId буде рядком "15".
main.jsximport { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
createRoot(document.getElementById("root")).render(
<StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>
);App.jsximport { Link, Route, Routes, useParams } from "react-router-dom";
const products = [
{
id: 1,
name: "Клавіатура",
price: 2500,
description: "Механічна клавіатура для роботи та ігор."
},
{
id: 2,
name: "Миша",
price: 1200,
description: "Бездротова миша з точним сенсором."
},
{
id: 3,
name: "Навушники",
price: 3200,
description: "Навушники із шумозаглушенням."
}
];
function HomePage() {
return (
<main>
<h1>Головна сторінка</h1>
<p>Виберіть товар зі списку.</p>
<Link to="/products">Переглянути товари</Link>
</main>
);
}
function ProductsPage() {
return (
<main>
<h1>Товари</h1>
<ul>
{products.map((product) => (
<li key={product.id}>
<Link to={`/products/${product.id}`}>
{product.name}
</Link>
</li>
))}
</ul>
</main>
);
}
function ProductPage() {
const { productId } = useParams();
const product = products.find(
(item) => item.id === Number(productId)
);
if (!product) {
return (
<main>
<h1>Товар не знайдено</h1>
<Link to="/products">Повернутися до списку товарів</Link>
</main>
);
}
return (
<main>
<h1>{product.name}</h1>
<p>{product.description}</p>
<p>Ціна: {product.price} грн</p>
<Link to="/products">Повернутися до списку товарів</Link>
</main>
);
}
function NotFoundPage() {
return (
<main>
<h1>Сторінку не знайдено</h1>
<Link to="/">На головну</Link>
</main>
);
}
function App() {
return (
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/products" element={<ProductsPage />} />
<Route path="/products/:productId" element={<ProductPage />} />
<Route path="*" element={<NotFoundPage />} />
</Routes>
);
}
export default App;Після запуску застосунку відкрийте сторінку зі списком товарів. Посилання сформують такі адреси:
/products/1
/products/2
/products/3Для кожної адреси React Router використає той самий компонент ProductPage, але useParams поверне різне значення productId.
Розглянемо маршрут:
<Route path="/products/:productId" element={<ProductPage />} />Якщо користувач відкриє:
/products/2то в компоненті ProductPage:
const { productId } = useParams();значенням productId буде рядок:
"2"Щоб знайти товар у масиві, його перетворено на число:
const product = products.find(
(item) => item.id === Number(productId)
);Якщо товар із таким ідентифікатором не існує, find поверне undefined. У такому випадку компонент показує повідомлення Товар не знайдено.
Для переходу на сторінку конкретного товару значення параметра додається до to:
<Link to={`/products/${product.id}`}>
{product.name}
</Link>Якщо product.id дорівнює 2, результатом буде:
/products/2Такий підхід зручніший за написання кожного посилання вручну, оскільки воно формується з даних товару.
Маршрут може містити більше одного параметра. Наприклад:
<Route
path="/categories/:categoryId/products/:productId"
element={<ProductPage />}
/>Для URL:
/categories/5/products/12хук useParams поверне:
const { categoryId, productId } = useParams();Значення будуть такими:
categoryId === "5"
productId === "12"Назви параметрів у useParams повинні збігатися з назвами параметрів у маршруті.
У маршруті:
/products/:productIdстатичною є частина:
/products/а динамічною —:
:productIdУ маршруті:
/users/:userId/orders/:orderIdє два динамічні параметри:
userId;
orderId.
Кожен із них доступний через useParams.
Неправильно:
<Route path="/products/productId" element={<ProductPage />} />Цей маршрут відповідає лише точній адресі:
/products/productIdПравильно:
<Route path="/products/:productId" element={<ProductPage />} />Тепер productId є динамічним параметром.
Якщо маршрут має параметр productId:
<Route path="/products/:productId" element={<ProductPage />} />отримувати його потрібно так:
const { productId } = useParams();А не так:
const { id } = useParams();id буде undefined, тому що такого параметра в маршруті немає.
Параметри URL є рядками:
const { productId } = useParams();
console.log(typeof productId); // "string"Якщо ідентифікатори в даних є числами, виконайте перетворення:
const product = products.find(
(item) => item.id === Number(productId)
);Користувач може вручну відкрити адресу:
/products/999Якщо такого товару немає, результат пошуку буде undefined. Перед використанням властивостей товару перевіряйте результат:
if (!product) {
return <p>Товар не знайдено</p>;
}useParams використовується поза маршрутомХук useParams отримує дані з активного маршруту. Його потрібно викликати в компоненті, який відображається цим маршрутом або є його дочірнім компонентом.
function ProductPage() {
const { productId } = useParams();
return <h1>Товар: {productId}</h1>;
}Створіть сторінку статті з динамічним маршрутом:
/articles/:articleIdДля цього:
Створіть масив статей з id, title і text.
Додайте список статей.
Для кожної статті створіть посилання /articles/${article.id}.
Створіть компонент ArticlePage.
Отримайте articleId через useParams.
Знайдіть статтю за ідентифікатором.
Покажіть повідомлення, якщо статтю не знайдено.
Динамічний сегмент маршруту записується після двокрапки: :productId.
Значення динамічного сегмента отримують через useParams.
Параметри URL завжди мають тип string.
Для пошуку числового ідентифікатора потрібно перетворити параметр через Number.
Один динамічний маршрут може обробляти багато різних URL.
Якщо даних за параметром немає, потрібно показати зрозуміле повідомлення користувачу.