Маршрутизация в React с React Router v6

TL;DR
React Router v6 — современная библиотека для маршрутизации в React: она упрощает вложенные маршруты, автоматически ранжирует совпадения и добавляет удобные хуки для навигации и состояния. Для простых приложений достаточно BrowserRouter и Routes/Route. Для централизованной конфигурации и расширенных сценариев используйте createBrowserRouter + RouterProvider и data API (v6.4+). В статье — практические примеры, советы по миграции, сценарии защиты маршрутов, чек-листы и краткий глоссарий.
Что такое React Router v6
React Router — библиотека для управления переходами в приложениях React. Версия 6 переработала алгоритм сопоставления маршрутов, добавила поддержку относительных маршрутов и новые API (хуки и провайдеры), которые делают конфигурацию яснее и безопаснее. Ключевая идея: маршруты — это дерево, которое мапится на дерево компонентов.
Начало работы
Создайте проект React (Create React App или Vite). Установите пакет:
npm install react-router-domНиже — пошаговые примеры конфигурации и полезные паттерны.
Обёртывание приложения BrowserRouter
Чтобы компоненты получили доступ к контексту маршрутизации, оберните приложение в BrowserRouter (обычно в index.jsx или main.jsx):
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import { BrowserRouter as Router } from 'react-router-dom'
ReactDOM.createRoot(document.getElementById('root')).render(
)BrowserRouter подходит для большинства приложений, где маршрутизация управляется на клиенте и нужен HTML5 history API.
Компоненты Routes и Route
Routes — замена Switch из v5. Она автоматически ранжирует маршруты и поддерживает относительные и вложенные маршруты.
Пример App.jsx:
import './App.css'
import { Routes, Route } from 'react-router-dom'
import Dashboard from './pages/Dashboard'
import About from './pages/About'
function App() {
return (
<>
} />
} />
>
)
}
export default AppОбратите внимание на свойство element — оно принимает JSX-элемент, поэтому вы можете передавать пропсы и оборачивать компонент в провайдеры.
Использование createBrowserRouter и RouterProvider
Если вы предпочитаете централизованную конфигурацию маршрутов (массив объектов), используйте createBrowserRouter и RouterProvider. Это полезно при большом количестве маршрутов, SSR-подходах или когда нужно декларативно задавать loaders/errorElement/actions.
import React from 'react'
import ReactDOM from 'react-dom/client'
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import App from './App.jsx'
import Dashboard from './pages/Dashboard'
import About from './pages/About'
const router = createBrowserRouter([
{ path: '/', element: },
{ path: '/dashboard', element: },
{ path: '/about', element: },
])
ReactDOM.createRoot(document.getElementById('root')).render(
)RouterProvider передаёт контекст маршрутизатора всем компонентам — аналога BrowserRouter не требуется в этом сценарии.
Важно: начиная с React Router v6.4 появился data API (loaders, actions, errorElement) — оно расширяет createBrowserRouter. Если ваш проект использует загрузку данных на уровне маршрутов, изучите соответствующие примеры в документации.
Маршрут «Страница не найдена» (404)
Используйте wildcard path “*” в Routes или в массиве createBrowserRouter для обработки несопадающих URL:
// с Route
} />
// с createBrowserRouter
{ path: '*', element: }Создайте компонент NotFound.jsx и стилизуйте его по дизайну приложения.
Программная навигация: useNavigate и useNavigation
useNavigate — хук для программной навигации (редирект по клику, после сабмита и т. п.).
import { useNavigate } from 'react-router-dom'
function About() {
const navigate = useNavigate()
const handleButtonClick = () => {
navigate('/')
}
return (
<>
{/* Остальная разметка */}
>
)
}
export default AboutuseNavigation возвращает текущее состояние навигации (например, “loading” или “submitting”) и полезен для отображения индикаторов загрузки:
import { useNavigation } from 'react-router-dom'
function SubmitButton() {
const navigation = useNavigation()
const buttonText =
navigation.state === 'submitting'
? 'Сохранение...'
: navigation.state === 'loading'
? 'Загрузка...'
: 'Отправить'
return
}Используйте оба хука вместе: useNavigate для перехода, useNavigation для показа прогресса.
Хук useRoutes
useRoutes позволяет описывать маршруты в виде массива объектов непосредственно в компоненте и возвращает результат сопоставления:
import { useRoutes } from 'react-router-dom'
import Dashboard from './Dashboard'
import About from './About'
const routes = [
{ path: '/', element: },
{ path: '/about', element: },
]
function App() {
const routeResult = useRoutes(routes)
return routeResult
}
export default AppЭто удобно, когда часть маршрутов зависит от состояния приложения или конфигурации.
Вложенные маршруты и индексные маршруты
Маршруты в v6 устроены как дерево: родительский маршрут рендерит Outlet, а дочерние рендерятся внутри него.
Пример вложения:
import { Outlet } from 'react-router-dom'
function DashboardLayout() {
return (
Управление
)
}
// Конфигурация
{ path: '/dashboard', element: , children: [
{ index: true, element: },
{ path: 'settings', element: },
]}index: true обозначает маршрут по умолчанию для родителя.
Параметры маршрута и query-параметры
Параметры пути доступны через useParams:
import { useParams } from 'react-router-dom'
function User() {
const { id } = useParams()
return Пользователь {id}
}Query-параметры не парсятся автоматически — используйте URLSearchParams вместе с useLocation:
import { useLocation } from 'react-router-dom'
function Search() {
const { search } = useLocation()
const params = new URLSearchParams(search)
const q = params.get('q')
return Результаты для: {q}
}Защита маршрутов (Protected Routes)
Один из распространённых паттернов — защищённый маршрут, который проверяет авторизацию и редиректит на страницу логина:
import { Navigate, Outlet } from 'react-router-dom'
function RequireAuth({ isAuthenticated }) {
if (!isAuthenticated) {
return
}
return
}
// Конфигурация
{ path: '/app', element: , children: [
{ path: 'profile', element: },
]}Этот шаблон прост и совместим с маршрутизаторами как BrowserRouter, так и createBrowserRouter.
Ленивый импорт компонентов и Suspense
Для уменьшения размера бандла используйте React.lazy и Suspense:
import React, { Suspense, lazy } from 'react'
const Dashboard = lazy(() => import('./pages/Dashboard'))
function App() {
return (
Загрузка... Если вы используете data API (v6.4+), комбинируйте loaders с ленивым рендером для оптимальной UX.
Data API (loaders, actions, errorElement)
В версиях React Router v6.4+ появился набор инструментов для загрузки данных и обработки ошибок на уровне маршрутов (loaders, actions, errorElement). Они удобны для серверных запросов, форм и декларативной обработки ошибок. Изучите документацию перед внедрением — это мощный инструмент, меняющий архитектуру работы с данными.
Модель мышления: маршруты как дерево
Ментальная модель: представьте маршруты как дерево папок в файловой системе. Родитель определяет общий shell (навигация, сайдбар), дочерние — содержимое. Outlet — место для рендера дочерних элементов.
Когда React Router не подходит (контрпримеры)
- Простая одностраничная страница с несколькими компонентами — можно обойтись без библиотеки.
- Если у вас серверная маршрутизация (традиционный серверный рендеринг), может быть проще использовать фреймворк с собственной маршрутизацией (Next.js, Remix).
- Для микрофронтендов с отдельными приложениями иногда удобнее иметь минимальные маршрутизаторы, чтобы не объединять глобальный контекст.
Практическая методология миграции с v5 на v6
- Обновите зависимости и запустите сборку.
- Замените Switch на Routes и компоненты Route (элемент — JSX).
- Проверьте вложенные маршруты: в v6 нужны Outlet и index-маршруты вместо exact.
- Замените useHistory на useNavigate.
- Тестируйте protected routes и редиректы (Navigate).
Чек-лист перед релизом (роль: разработчик)
- Все маршруты корректно отображаются при прямом вводе URL
- Нет конфликтующих путей (динамические и статические)
- 404-страница настроена
- Ленивая подгрузка критичных страниц работает
- Protected routes корректно редиректят
- Формы используют action/loader (если применимо)
Критерии приёмки
- Навигация работает без перезагрузки страницы.
- URL изменяется корректно при переходах.
- При недоступном ресурсе отображается NotFound.
- Защищённые страницы доступны только авторизованным пользователям.
Справочник — 1‑строчный глоссарий
- BrowserRouter: провайдер, использующий history API.
- Routes/Route: декларация совпадений URL → элемент.
- RouterProvider: провайдер для createBrowserRouter.
- useNavigate: программный переход.
- useNavigation: информация о текущем переходе.
- Outlet: место для рендера дочерних маршрутов.
- loader/action: загрузка/обработка данных на уровне маршрута (v6.4+).
Решающее дерево выбора API (Mermaid)
flowchart TD
A[Нужна централизованная конфигурация?] -->|Да| B[createBrowserRouter + RouterProvider]
A -->|Нет| C[BrowserRouter + Routes]
B --> D{Нужны loaders/actions/errorElement?}
D -->|Да| E[Использовать data API 'v6.4+']
D -->|Нет| F[Обычная конфигурация маршрутов]
C --> G{Должны ли маршруты динамически меняться?}
G -->|Да| H[useRoutes внутри компонента]
G -->|Нет| F(Для визуализации убедитесь, что ваш рендерер поддерживает Mermaid.)
Шаблонный код: Protected Route Snippet
import { Navigate, Outlet } from 'react-router-dom'
export function ProtectedRoute({ isAuthed, redirectTo = '/login' }) {
return isAuthed ? :
}Советы по производительности и безопасности
- Минимизируйте количество одновременно загружаемых маршрутов через ленивую загрузку.
- Не храните секреты в URL.
- Для больших приложений разбивайте маршруты по фичам и используйте code-splitting.
Локальные особенности и миграционные хитрости
- В проектах с TypeScript обязательно добавьте типы для loader/action.
- При миграции следите за использованием exact и component — в v6 их нет.
- Проверьте серверную настройку: при прямом переходе на URL сервер должен отдавать index.html (SPA).
Резюме
React Router v6 делает маршрутизацию яснее и мощнее: современный синтаксис, автоматическое ранжирование, удобные хуки и расширяемый data API. Для небольших приложений достаточно BrowserRouter + Routes, а для сложных — createBrowserRouter с loaders/actions и RouterProvider. При миграции обратите внимание на замену Switch → Routes, useHistory → useNavigate и на работу вложенных роутов через Outlet.
Важно: выбирайте подходящий API под архитектуру приложения, тестируйте прямые переходы по URL и настройте поведение 404/Protected-Route заранее.
Похожие материалы
Создать пошаговое руководство с Steps Recorder
Ромбовидное наследование в C++ и как его решать
Удвоить скорость прокрутки в TikTok
Установка Discord на Linux — пошагово
Как восстановить черновики TikTok