React Router предоставляет гибкие механизмы для построения маршрутов в приложениях на React, включая вложенные маршруты, динамические параметры и условную навигацию. Композиция маршрутов позволяет организовать структуру приложения так, чтобы каждый компонент маршрута мог управлять своими подмаршрутами и состоянием, обеспечивая модульность и читаемость кода.
В React Router (версии 6 и выше) вложенные маршруты задаются через
Routes и Route, где один маршрут может
содержать другие маршруты в качестве дочерних. Это позволяет создавать
многоуровневые структуры, которые отражают архитектуру приложения.
Пример вложенного маршрута:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Dashboard from './Dashboard';
import Profile from './Profile';
import Settings from './Settings';
function App() {
return (
<Router>
<Routes>
<Route path="/dashboard" element={<Dashboard />}>
<Route path="profile" element={<Profile />} />
<Route path="settings" element={<Settings />} />
</Route>
</Routes>
</Router>
);
}
В этом примере Profile и Settings являются
подмаршрутами Dashboard. Для отображения вложенного
содержимого внутри компонента Dashboard используется
<Outlet />:
import { Outlet } from 'react-router-dom';
function Dashboard() {
return (
<div>
<h1>Панель управления</h1>
<Outlet />
</div>
);
}
<Outlet /> рендерит дочерние маршруты, позволяя
создать шаблон страницы с общей структурой.
Динамические сегменты маршрута позволяют передавать данные через URL.
Для этого в path используется синтаксис с двоеточием
(:):
<Route path="/user/:userId" element={<UserProfile />} />
Внутри компонента можно получить значение параметра через хук
useParams:
import { useParams } from 'react-router-dom';
function UserProfile() {
const { userId } = useParams();
return <div>Профиль пользователя: {userId}</div>;
}
Динамические параметры удобно комбинировать с вложенными маршрутами для создания страниц профиля с вкладками:
<Route path="/user/:userId" element={<UserProfile />}>
<Route path="posts" element={<UserPosts />} />
<Route path="settings" element={<UserSettings />} />
</Route>
Индексные маршруты используются для отображения содержимого по
умолчанию при переходе на родительский маршрут. Они объявляются с
помощью атрибута index:
<Route path="/dashboard" element={<Dashboard />}>
<Route index element={<DashboardHome />} />
<Route path="profile" element={<Profile />} />
</Route>
При переходе на /dashboard будет рендериться
DashboardHome, а при /dashboard/profile —
компонент Profile.
Для оптимизации приложения можно использовать ленивую загрузку
компонентов маршрутов через React.lazy и
Suspense. Это особенно полезно для крупных приложений с
большим числом страниц:
import { Suspense, lazy } from 'react';
import { Routes, Route } from 'react-router-dom';
const Dashboard = lazy(() => import('./Dashboard'));
const Profile = lazy(() => import('./Profile'));
function App() {
return (
<Suspense fallback={<div>Загрузка...</div>}>
<Routes>
<Route path="/dashboard" element={<Dashboard />}>
<Route path="profile" element={<Profile />} />
</Route>
</Routes>
</Suspense>
);
}
Композиция маршрутов позволяет легко реализовать защищённые маршруты
через обёртки-компоненты. Например, компонент PrivateRoute
проверяет авторизацию перед рендером дочерних маршрутов:
import { Navigate, Outlet } from 'react-router-dom';
function PrivateRoute({ isAuthenticated }) {
return isAuthenticated ? <Outlet /> : <Navigate to="/login" />;
}
// Использование
<Route element={<PrivateRoute isAuthenticated={true} />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/dashboard/profile" element={<Profile />} />
</Route>
React Router поддерживает динамическое формирование маршрутов на основе состояния приложения. Это позволяет создавать конфигурации маршрутов программно:
const routes = [
{ path: '/home', element: <Home /> },
{ path: '/about', element: <About /> },
];
function App() {
return (
<Routes>
{routes.map((route, index) => (
<Route key={index} path={route.path} element={route.element} />
))}
</Routes>
);
}
Такой подход упрощает управление маршрутизацией при масштабировании приложения.
Для перехода между маршрутами используются компоненты
Link и NavLink. NavLink позволяет
добавить активное состояние для текущего маршрута:
import { NavLink } from 'react-router-dom';
function Navigation() {
return (
<nav>
<NavLink to="/home" className={({ isActive }) => isActive ? 'active' : ''}>Главная</NavLink>
<NavLink to="/about" className={({ isActive }) => isActive ? 'active' : ''}>О проекте</NavLink>
</nav>
);
}
Link и NavLink поддерживают как
относительные, так и абсолютные пути, что упрощает работу с вложенными
маршрутами.
Для обработки ошибок навигации используется маршрут с
path="*":
<Route path="*" element={<NotFound />} />
Он отрабатывает, если ни один другой маршрут не совпадает с текущим URL. Комбинируя его с вложенными маршрутами, можно создавать сложные структуры ошибок для разных секций приложения.
Композируемые маршруты в React Router позволяют строить модульные, масштабируемые и гибкие структуры приложений. Важнейшие элементы композиции — вложенные маршруты, индексные маршруты, динамические параметры, ленивые компоненты и условная навигация. Правильное использование этих инструментов повышает читаемость кода и упрощает поддержку больших приложений.