Маршрутизация в React — навигация по компонентам
Содержание
- Введение: зачем нужен роутер в React
- Почему @reach/router больше не используется
- React Router v6 — установка и базовый синтаксис
- Навигация с помощью Link и NavLink
- Вложенные маршруты (Nested Routes)
- Параметры маршрута (Route Parameters)
- Query-параметры (строка запроса)
- Защищённые маршруты (Private Routes)
- Lazy Loading (ленивая загрузка маршрутов)
- React Router v6.4+ — Data Router (расширенные возможности)
- Сравнительная таблица: React Router vs @reach/router
- Частые ошибки новичков
- Итог (что мы узнали)
- Задание для закрепления (на 1–2 часа)
- Что дальше?
Цель урока: научиться создавать многостраничные React-приложения с помощью React Router. Понять, как работают маршруты, навигация, вложенные маршруты и защищённые страницы. Узнать, почему @reach/router больше не используется и что выбрать для новых проектов.
Введение: зачем нужен роутер в React
Проблема:
Как сделать так, чтобы при переходе по URL /about показывалась одна страница, а при /profile — другая?
Главная мысль: роутер синхронизирует URL и интерфейс. Когда пользователь переходит по ссылке или вводит адрес вручную, роутер определяет, какой компонент показать.
Две основные библиотеки:
- React Router — стандарт де-факто для React, активно развивается
@reach/router— устаревшая библиотека, не рекомендуется для новых проектов
Почему @reach/router больше не используется
Важно: @reach/router официально устарел (deprecated). Вместо него используйте React Router v6+.
Причины:
- Разработка остановлена
- Авторы объединили лучшие идеи из обеих библиотек в React Router v6
- React Router v6 стал меньше по размеру и мощнее по возможностям
Что произошло:
React Router и @reach/router объединились. Если бы существовал @reach/router v2, он выглядел бы как React Router v6. Поэтому в новых проектах всегда выбирайте React Router.
React Router v6 — установка и базовый синтаксис
Установка:
npm install react-router-dom@6
Базовый пример:
import { BrowserRouter, Routes, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/contact" element={<ContactPage />} />
<Route path="*" element={<NotFoundPage />} />
</Routes>
</BrowserRouter>
);
}
Что здесь происходит:
BrowserRouter— обёртка, дающая доступ к URLRoutes— контейнер для маршрутов (заменил Switch)Route— определяет соответствие пути и компонентаpath="*"— «ловит» все несуществующие пути (404)
Навигация с помощью Link и NavLink
Link — для обычных переходов:
import { Link } from 'react-router-dom';
function Navigation() {
return (
<nav>
<Link to="/">Главная</Link>
<Link to="/about">О нас</Link>
<Link to="/contact">Контакты</Link>
</nav>
);
}
NavLink — для активных ссылок:
import { NavLink } from 'react-router-dom';
function Navigation() {
return (
<nav>
<NavLink
to="/"
className={({ isActive }) => isActive ? 'active' : ''}
>
Главная
</NavLink>
<NavLink
to="/about"
style={({ isActive }) => ({
color: isActive ? 'red' : 'black'
})}
>
О нас
</NavLink>
</nav>
);
}
Программная навигация (через код):
import { useNavigate } from 'react-router-dom';
function LoginButton() {
const navigate = useNavigate();
const handleLogin = () => {
// После успешного входа перенаправляем
navigate('/dashboard');
};
return <button onClick={handleLogin}>Войти</button>;
}
Оживи свой сайт. Освой JavaScript!
Статичная верстка — это только скелет. Наш онлайн-курс "JavaScript с нуля до профи" даст твоим страницам мышцы и нервы. Научись создавать слайдеры, формы, интерактивные карты и получать данные с сервера.
От теории — к реальным скриптам в твоём портфолио.
Вложенные маршруты (Nested Routes)
Одна из главных фишек React Router — возможность вкладывать маршруты друг в друга.
Структура:
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<HomePage />} />
<Route path="about" element={<AboutPage />} />
<Route path="dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardHome />} />
<Route path="settings" element={<Settings />} />
<Route path="profile" element={<Profile />} />
</Route>
</Route>
</Routes>
</BrowserRouter>
);
}
Компонент Layout с Outlet:
import { Outlet, Link } from 'react-router-dom';
function Layout() {
return (
<div>
<header>
<nav>
<Link to="/">Главная</Link>
<Link to="/about">О нас</Link>
<Link to="/dashboard">Панель</Link>
</nav>
</header>
<main>
<Outlet /> {/* Здесь рендерятся вложенные маршруты */}
</main>
<footer>Подвал</footer>
</div>
);
}
Что дают вложенные маршруты:
- Общий макет (хедер, сайдбар, футер) для группы страниц
- Изоляция логики на разных уровнях
- Чистая структура кода
Параметры маршрута (Route Parameters)
Динамические сегменты URL:
// Определение маршрута с параметром
<Route path="/users/:userId" element={<UserProfile />} />
Получение параметров в компоненте:
import { useParams } from 'react-router-dom';
function UserProfile() {
const { userId } = useParams();
return <h1>Профиль пользователя {userId}</h1>;
}
// /users/123 → userId = "123"
Несколько параметров:
<Route path="/products/:category/:productId" element={<Product />} />
function Product() {
const { category, productId } = useParams();
return <p>Категория: {category}, Товар: {productId}</p>;
}
Query-параметры (строка запроса)
Доступ к query-параметрам:
import { useLocation } from 'react-router-dom';
function SearchPage() {
const location = useLocation();
const searchParams = new URLSearchParams(location.search);
const query = searchParams.get('q');
const page = searchParams.get('page') || '1';
return <p>Поиск: {query}, Страница: {page}</p>;
}
// /search?q=react&page=2 → query = "react", page = "2"
Защищённые маршруты (Private Routes)
Компонент-обёртка для проверки авторизации:
import { Navigate, Outlet } from 'react-router-dom';
function ProtectedRoute({ isAuthenticated }) {
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
return <Outlet />;
}
// Использование
function App() {
const [isAuth, setIsAuth] = useState(false);
return (
<BrowserRouter>
<Routes>
<Route path="/login" element={<Login />} />
<Route element={<ProtectedRoute isAuthenticated={isAuth} />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/profile" element={<Profile />} />
<Route path="/settings" element={<Settings />} />
</Route>
<Route path="*" element={<NotFound />} />
</Routes>
</BrowserRouter>
);
}
Lazy Loading (ленивая загрузка маршрутов)
Оптимизация производительности — загрузка кода страницы только когда она нужна:
import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
const HomePage = lazy(() => import('./pages/HomePage'));
const AboutPage = lazy(() => import('./pages/AboutPage'));
const DashboardPage = lazy(() => import('./pages/DashboardPage'));
function App() {
return (
<BrowserRouter>
<Suspense fallback={<div>Загрузка...</div>}>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/dashboard" element={<DashboardPage />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
React Router v6.4+ — Data Router (расширенные возможности)
Начиная с версии 6.4, появился Data Router с поддержкой:
| Возможность | Что даёт |
|---|---|
| Loaders | Загрузка данных до рендера компонента |
| Actions | Обработка отправки форм |
| Error Boundaries | Отлов ошибок на уровне маршрутов |
Пример с loader:
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
const router = createBrowserRouter([
{
path: '/users/:id',
element: <UserDetail />,
loader: async ({ params }) => {
const response = await fetch(`/api/users/${params.id}`);
if (!response.ok) throw new Error('Пользователь не найден');
return response.json();
},
errorElement: <ErrorPage />
}
]);
function App() {
return <RouterProvider router={router} />;
}
Почему это лучше useEffect?
- Данные загружаются до рендера, нет «моргания» загрузки
- Поддержка параллельной загрузки данных
- Встроенная обработка ошибок
Сравнительная таблица: React Router vs @reach/router
| Характеристика | React Router v6 | @reach/router |
|---|---|---|
| Статус | Активно развивается | Устарел (deprecated) |
| Кому принадлежит | React Training + Remix | Команда React (передана) |
| Размер | ~3kb (оптимизирован) | Больше |
| Вложенные маршруты | ✅ Отличная поддержка | ✅ Были основой |
| Хуки | useParams, useNavigate, useLocation |
Есть, но устарели |
| Data Router | ✅ Да (v6.4+) | ❌ Нет |
| Перспектива | Единственный выбор для новых проектов | Не рекомендуется |
Частые ошибки новичков
| Ошибка | Почему | Исправление |
|---|---|---|
Забывают обернуть в BrowserRouter |
Routes не работают |
Добавь <BrowserRouter> на верхний уровень |
Используют Switch вместо Routes |
Синтаксис старой версии | Обнови до Routes |
Не закрывают тег Route |
Ошибка синтаксиса | Правильно: <Route path="/" element={<Page />} /> |
Забывают * для 404 |
Несуществующие пути не обрабатываются | Добавь <Route path="*" element={<NotFound />} /> |
Пытаются использовать @reach/router |
Библиотека устарела | Используй react-router-dom v6+ |
Итог (что мы узнали)
| Что узнали | Как это работает |
|---|---|
| React Router vs @reach/router | @reach/router устарел, React Router — стандарт |
BrowserRouter |
Обёртка для маршрутизации |
Routes и Route |
Контейнеры для путей и компонентов |
Link и NavLink |
Навигация без перезагрузки |
useNavigate |
Программная навигация |
| Вложенные маршруты | Outlet для вложенных компонентов |
useParams |
Доступ к динамическим параметрам |
useLocation |
Доступ к query-параметрам |
| Защищённые маршруты | Проверка авторизации через Navigate |
| Data Router | Загрузка данных до рендера (v6.4+) |
Задание для закрепления (на 1–2 часа)
Создай полноценное многостраничное приложение:
- Главная страница (
/) — приветствие и ссылки на другие страницы - О нас (
/about) — информация о проекте - Профиль пользователя (
/users/:id) — показывает имя и email пользователя (используйuseParams) - Поиск (
/search?q=...) — показывает поисковый запрос из URL 404— для всех несуществующих путей- Защищённый раздел (
/admin) — доступен только приisAuthenticated === true(используйProtectedRoute)
Дополнительно:
- Используй
NavLinkс активным стилем для меню - Добавь ленивую загрузку для страниц
- (Опционально) Используй
createBrowserRouterсloaderдля загрузки данных пользователя по ID
Проверка: убедись, что все маршруты работают корректно, навигация происходит без перезагрузки страницы, а защищённый раздел недоступен без авторизации.
Пример выполненного задания

Скачать код выполненного задания: (откроется в новой вкладке)React Router.
Что дальше?
В следующем уроке разберём SSR (Server Side Rendering) с Next.js — как создавать React-приложения, которые рендерятся на сервере. Ты узнаешь, как улучшить SEO, ускорить загрузку и создавать полноценные веб-приложения с Next.js.