Вложенные маршруты

В React Router вложенные маршруты позволяют организовать сложные интерфейсы с иерархией страниц, где один компонент маршрута может содержать другие маршруты. Это особенно полезно при построении приложений с панелями, сайдбарами, вкладками и динамическими страницами.


Структура вложенных маршрутов

Для создания вложенных маршрутов используется комбинация компонентов <Routes> и <Route> внутри родительского компонента. В React Router v6 вложенные маршруты задаются с помощью свойства element для родителя и вложенных <Route> внутри него:

import { Routes, Route, Outlet } from 'react-router-dom';
import Dashboard from './Dashboard';
import Profile from './Profile';
import Settings from './Settings';

function App() {
  return (
    <Routes>
      <Route path="/dashboard" element={<Dashboard />}>
        <Route path="profile" element={<Profile />} />
        <Route path="settings" element={<Settings />} />
      </Route>
    </Routes>
  );
}

export default App;

Здесь Dashboard является родительским компонентом. Внутри него определены два вложенных маршрута — Profile и Settings. Чтобы эти маршруты отображались внутри Dashboard, используется компонент <Outlet>:

function Dashboard() {
  return (
    <div>
      <h1>Панель управления</h1>
      <Outlet />
    </div>
  );
}

<Outlet /> выполняет роль “места под маршруты”, куда будут рендериться вложенные компоненты в зависимости от текущего URL.


Абсолютные и относительные пути

Вложенные маршруты могут использовать относительные пути, которые уточняются относительно родителя:

  • path="profile"/dashboard/profile
  • path="settings"/dashboard/settings

Для абсолютных путей можно указывать полный путь:

<Route path="/dashboard/profile" element={<Profile />} />

Однако рекомендуется использовать относительные пути внутри вложенных маршрутов, чтобы структура оставалась гибкой при изменении базового URL.


Индексные маршруты

Для родительского маршрута можно задать индексный маршрут, который рендерится по умолчанию, если URL совпадает с родителем:

<Route path="/dashboard" element={<Dashboard />}>
  <Route index element={<Profile />} />
  <Route path="settings" element={<Settings />} />
</Route>

В этом примере при переходе на /dashboard автоматически рендерится Profile. Индексный маршрут используется вместо обычного path, когда нужно показывать компонент по умолчанию внутри родителя.


Навигация внутри вложенных маршрутов

Для перехода между вложенными маршрутами применяется компонент <Link> с относительными или абсолютными путями:

import { Link } from 'react-router-dom';

function DashboardMenu() {
  return (
    <nav>
      <Link to="">Профиль</Link>
      <Link to="settings">Настройки</Link>
    </nav>
  );
}
  • to="" — относительный путь к индексному маршруту родителя.
  • to="settings" — относительный путь к маршруту settings.

Использование относительных ссылок упрощает управление вложенными маршрутизируемыми компонентами и делает структуру более модульной.


Динамические вложенные маршруты

React Router поддерживает параметры маршрутов внутри вложенных маршрутов:

<Route path="/dashboard" element={<Dashboard />}>
  <Route path="user/:id" element={<UserProfile />} />
</Route>

В компоненте UserProfile можно получить параметр id через хук useParams:

import { useParams } from 'react-router-dom';

function UserProfile() {
  const { id } = useParams();
  return <div>Профиль пользователя: {id}</div>;
}

Это позволяет строить динамические вложенные маршруты, например, для страниц пользователей, статей или товаров.


Protected и вложенные маршруты

Для реализации защищённых страниц (требующих авторизации) вложенные маршруты удобно комбинировать с компонентом-обёрткой:

function ProtectedRoute({ element }) {
  const isAuthenticated = checkAuth();
  return isAuthenticated ? element : <Navigate to="/login" />;
}

<Routes>
  <Route path="/dashboard" element={<ProtectedRoute element={<Dashboard />} />}>
    <Route path="settings" element={<Settings />} />
  </Route>
</Routes>

Все вложенные маршруты родителя Dashboard автоматически наследуют защиту, что упрощает управление доступом к нескольким страницам одновременно.


Сложные вложенные структуры

Вложенные маршруты могут быть многоуровневыми, что позволяет строить глубокие интерфейсы:

<Route path="/dashboard" element={<Dashboard />}>
  <Route path="projects" element={<Projects />}>
    <Route path=":projectId" element={<ProjectDetails />}>
      <Route path="tasks" element={<Tasks />} />
    </Route>
  </Route>
</Route>

Для каждого уровня используется <Outlet /> внутри родительского компонента. Это создаёт иерархию, в которой каждый уровень маршрута управляет своим контентом.


Важные моменты

  • <Outlet /> обязателен для рендеринга вложенных маршрутов.
  • Индексные маршруты упрощают отображение контента по умолчанию.
  • Относительные пути повышают гибкость и повторное использование компонентов.
  • Динамические параметры маршрутов работают и на вложенных уровнях.
  • Защита родительского маршрута автоматически распространяется на все вложенные маршруты.

Вложенные маршруты делают структуру приложения более модульной, иерархичной и управляемой, что особенно важно для крупных проектов с множеством страниц и разделов.