Основы вложенной маршрутизации
Вложенные маршруты позволяют нам организовать приложение так, чтобы маршруты могли быть "вложены" друг в друга, подобно структуре папок на вашем компьютере. Например, если у нас есть раздел /dashboard, в нём могут быть вложенные страницы /dashboard/profile, /dashboard/settings и т.д. Это позволяет создавать больше модульности и удобства в построении сложных интерфейсов.
Для вложенной маршрутизации мы просто вкладываем компонент Route внутрь другого компонента. Главный родительский компонент будет отображаться всегда, а вложенный маршрут будет подгружаться в зависимости от URL.
Рассмотрим пример. Предположим, у нас есть страница "Dashboard" с двумя вложенными страницами: "Profile" и "Settings". Вот как это выглядит в коде:
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link, useRouteMatch } from 'react-router-dom';
// Компоненты для вложенных маршрутов
const Profile = () => <h2>Это ваш профиль</h2>;
const Settings = () => <h2>Настройки аккаунта</h2>;
const Dashboard = () => {
const { path, url } = useRouteMatch(); // useRouteMatch дает текущий путь и URL
return (
<div>
<h1>Добро пожаловать в Dashboard</h1>
<nav>
{/* Ссылки на вложенные маршруты */}
<Link to={`${url}/profile`}>Профиль</Link> |{' '}
<Link to={`${url}/settings`}>Настройки</Link>
</nav>
<Switch>
<Route path={`${path}/profile`} component={Profile} />
<Route path={`${path}/settings`} component={Settings} />
<Route path={path}>
<h2>Выберите раздел Dashboard</h2>
</Route>
</Switch>
</div>
);
};
const App = () => (
<Router>
<Switch>
<Route path="/dashboard" component={Dashboard} />
<Route path="/">
<h1>Главная страница</h1>
</Route>
</Switch>
</Router>
);
export default App;
Что здесь происходит:
- Компонент
Dashboardпоказывает ссылки для перехода на страницы "Profile" и "Settings". - Мы используем
useRouteMatchдля получения текущего путиpathи URLurl.pathиспользуется для определения маршрутов вRoute.urlиспользуется для создания ссылок.
- Каждый вложенный маршрут
/dashboard/profile,/dashboard/settingsопределяется внутри компонентаDashboard.
Когда пользователь переходит по ссылке "Профиль", его путь изменяется на /dashboard/profile, и мы видим компонент Profile.
Работа с динамическими маршрутами
Динамические маршруты позволяют передавать параметры прямо в URL, например, /user/:id для отображения информации о пользователе с уникальным ID. Это полезно для всех приложений, где страницы зависят от данных.
Чтобы объявить его динамичным, мы используем символ : перед параметром маршрута. Например, в маршруте /user/:id параметр id будет извлекаться динамически и передаваться в компонент.
Как насчет примера создания динамических маршрутов?
Предположим, у нас есть список пользователей, и мы хотим отображать отдельную страницу для каждого пользователя. Вот как это реализовать:
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link, useParams } from 'react-router-dom';
const User = () => {
const { id } = useParams>{ id: string }>(); // Используем useParams для получения параметра id
return <h2>Пользователь с ID: {id}</h2>;
};
const UsersList = () => {
const users = [
{ id: '1', name: 'Алиса' },
{ id: '2', name: 'Боб' },
{ id: '3', name: 'Чарли' },
];
return (
<div>
<h1>Список пользователей</h1>
<ul>
{users.map(user => (
<li key={user.id}>
<Link to={`/user/${user.id}`}>{user.name}</Link>
</li>
))}
</ul>
</div>
);
};
const App = () => (
<Router>
<Switch>
<Route path="/user/:id" component={User} /> {/* Динамический маршрут */}
<Route path="/" component={UsersList} />
</Switch>
</Router>
);
export default App;
Что здесь происходит:
- Мы создаём список пользователей с уникальными ID.
- Каждая ссылка в списке указывает на маршрут
/user/:id. - Компонент
Userизвлекает параметрidиз URL с помощью хукаuseParams. - Мы типизировали
useParams, указав, что параметрid— это строка.
Таким образом, каждая ссылка открывает динамическую страницу с соответствующим ID.
Практическое задание: совместим вложенные и динамические маршруты
А теперь объединяем все изученные концепции. Представьте приложение для онлайн-курсов, где у курса есть список уроков. Страница курса /course/:courseId должна показывать описание курса и список уроков с динамическими ссылками на каждый урок /course/:courseId/lesson/:lessonId.
Рекомендуемая структура приложения:
- Главная страница с курсами:
/courses. - Страница курса:
/course/:courseId. - Страница урока:
/course/:courseId/lesson/:lessonId.
Пример реализации:
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link, useParams, useRouteMatch } from 'react-router-dom';
const Lesson = () => {
const { courseId, lessonId } = useParams<{ courseId: string; lessonId: string }>();
return <h2>Курс {courseId}, урок {lessonId}</h2>;
};
const Course = () => {
const { courseId } = useParams>{ courseId: string }>();
const { url, path } = useRouteMatch();
const lessons = ['Введение', 'Основы', 'Заключение'];
return (
<div>
<h1>Курс: {courseId}</h1>
<ul>
{lessons.map((lesson, index) => (
<li key={index}>
<Link to={`${url}/lesson/${index + 1}`}>{lesson}</Link>
</li>
))}
</ul>
<Switch>
<Route path={`${path}/lesson/:lessonId`} component={Lesson} />
<Route path={path}>
<h2>Выберите урок</h2>
</Route>
</Switch>
</div>
);
};
const Courses = () => (
<div>
<h1>Список курсов</h1>
<ul>
<li><Link to="/course/react">Курс React</Link></li>
<li><Link to="/course/typescript">Курс TypeScript</Link></li>
</ul>
</div>
);
const App = () => (
<Router>
<Switch>
<Route path="/course/:courseId" component={Course} />
<Route path="/courses" component={Courses} />
<Route path="/">
<h1>Добро пожаловать на платформу!</h1>
<Link to="/courses">Перейти к курсам</Link>
</Route>
</Switch>
</Router>
);
export default App;
Теперь вы создали маршруты, которые могут быть одновременно вложенными и динамическими. Вы умеете типизировать параметры динамических маршрутов и строить сложные навигационные структуры.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ