Что такое React Router и как реализовать маршрутизацию?

MiddleReact · Frontend·Обновлено 20 июля 2026
Коротко
React Router — библиотека для клиентской маршрутизации в React-приложениях, позволяющая связывать URL с компонентами без перезагрузки страницы. Маршрутизация реализуется через обёртку BrowserRouter и набор компонентов Route, Link и хуков навигации.

Что такое React Router

React Router — стандартная библиотека маршрутизации для React. Она позволяет строить Single Page Application (SPA), где переходы между «страницами» происходят на стороне клиента: URL меняется, нужный компонент рендерится, но полная перезагрузка браузера не происходит.

Актуальная версия — React Router v6, которая существенно отличается от v5 синтаксисом и концепциями.

Основные концепции

BrowserRouter

Корневой провайдер, который подключает History API браузера. Оборачивает всё приложение:

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

function App() {
  return (
    <BrowserRouter>
      <Layout />
    </BrowserRouter>
  );
}

Routes и Route

Компонент Routes выбирает первый подходящий маршрут из набора Route. В v6 больше нет Switch — его заменил Routes:

import { Routes, Route } from 'react-router-dom';

function AppRoutes() {
  return (
    <Routes>
      <Route path="/" element={<HomePage />} />
      <Route path="/courses" element={<CoursesPage />} />
      <Route path="/courses/:id" element={<CourseDetailPage />} />
      <Route path="*" element={<NotFoundPage />} />
    </Routes>
  );
}

Вложенные маршруты (Nested Routes)

v6 поддерживает вложенность через дочерние Route и компонент Outlet:

function AppRoutes() {
  return (
    <Routes>
      <Route path="/dashboard" element={<DashboardLayout />}>
        {/* Outlet в DashboardLayout рендерит эти дочерние маршруты */}
        <Route index element={<DashboardHome />} />
        <Route path="profile" element={<ProfilePage />} />
        <Route path="settings" element={<SettingsPage />} />
      </Route>
    </Routes>
  );
}

function DashboardLayout() {
  return (
    <div>
      <Sidebar />
      <Outlet /> {/* сюда вставляется активный дочерний маршрут */}
    </div>
  );
}

Навигация

Для ссылок используется Link (без перезагрузки) или NavLink (с поддержкой активного состояния):

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

function Nav() {
  return (
    <nav>
      <NavLink
        to="/courses"
        className={({ isActive }) => isActive ? 'active' : ''}
      >
        Курсы
      </NavLink>
    </nav>
  );
}

Программная навигация и хуки

import { useNavigate, useParams, useSearchParams } from 'react-router-dom';

function CourseDetailPage() {
  const { id } = useParams<{ id: string }>();       // параметры пути
  const [searchParams] = useSearchParams();          // query-параметры
  const navigate = useNavigate();                    // программный переход

  const handleBack = () => navigate(-1);             // назад в истории
  const handleHome = () => navigate('/', { replace: true }); // без записи в историю

  return <div>Курс {id}</div>;
}

Защищённые маршруты

Паттерн для авторизованных зон:

function PrivateRoute({ children }: { children: React.ReactNode }) {
  const { isAuthenticated } = useAuth();
  return isAuthenticated ? <>{children}</> : <Navigate to="/login" replace />;
}

// Использование
<Route
  path="/dashboard"
  element={
    <PrivateRoute>
      <DashboardLayout />
    </PrivateRoute>
  }
/>

Ключевые отличия v6 от v5

  • SwitchRoutes
  • component={Page}element={<Page />}
  • useHistoryuseNavigate
  • Вложенные маршруты декларируются внутри родительского Route, а не в дочернем компоненте
  • Относительные пути работают автоматически в дочерних Route

Что хочет услышать интервьюер

Понимание разницы между серверной и клиентской маршрутизацией, знание что SPA не перезагружает страницу

Знание ключевых компонентов v6: BrowserRouter, Routes, Route, Link, Outlet и их роли

Умение работать с динамическими сегментами через useParams и query-параметрами через useSearchParams

Знание паттерна вложенных маршрутов с Outlet для построения layout-иерархии

Понимание как реализовать защищённые маршруты (Private Route) с редиректом на логин

Пример: Базовая настройка маршрутизации в приложении

// main.tsx
import { BrowserRouter } from 'react-router-dom';
import { App } from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

// App.tsx
import { Routes, Route, Navigate } from 'react-router-dom';

export function App() {
  return (
    <Routes>
      <Route path="/" element={<Navigate to="/courses" replace />} />
      <Route path="/courses" element={<CoursesPage />} />
      <Route path="/courses/:id" element={<CourseDetailPage />} />
      <Route
        path="/dashboard"
        element={
          <PrivateRoute>
            <DashboardLayout />
          </PrivateRoute>
        }
      >
        <Route index element={<DashboardHome />} />
        <Route path="profile" element={<ProfilePage />} />
      </Route>
      <Route path="*" element={<NotFoundPage />} />
    </Routes>
  );
}

Пример: Хуки навигации и работа с параметрами

import { useNavigate, useParams, useSearchParams } from 'react-router-dom';

function CourseDetailPage() {
  // Достаём динамический сегмент /courses/:id
  const { id } = useParams<{ id: string }>();

  // Читаем и пишем query-параметры (?tab=overview)
  const [searchParams, setSearchParams] = useSearchParams();
  const activeTab = searchParams.get('tab') ?? 'overview';

  const navigate = useNavigate();

  const handleEnroll = async () => {
    await enrollToCourse(id!);
    // replace: true — не добавляет запись в историю, нельзя вернуться назад
    navigate('/dashboard', { replace: true });
  };

  return (
    <div>
      <h1>Курс {id}</h1>
      <button onClick={() => setSearchParams({ tab: 'lessons' })}>Уроки</button>
      <button onClick={handleEnroll}>Записаться</button>
    </div>
  );
}

Типичные ошибки

Путаница между v5 и v6: использование Switch, component=, useHistory — API, которых в v6 нет

Отсутствие fallback-маршрута path="*" — при неизвестном URL пользователь видит пустой экран

Использование тега <a> вместо <Link>, что вызывает полную перезагрузку страницы

Неправильное размещение BrowserRouter — оборачивать нужно корень приложения, а не отдельные компоненты

Дублирование маршрутов в дочерних компонентах вместо использования вложенных Route с Outlet

Лучшие курсы по теме

изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Feature-Sliced Design

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.5
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее