Баннер мобильный (3) Пройти тест

Что такое маршрутизация в React Router и как ее настроить

Изучаем основы роутинга и собираем сайт-портфолио с ниндзями-волейболистами

Инструкция

19 февраля 2026

Поделиться

Скопировано
Что такое маршрутизация в React Router и как ее настроить

Содержание

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

    Допустим, вы хотите сделать сайт-портфолио. На нем будет главная страница, страница «О себе» и список проектов. И вот вам необходимо сделать так, чтобы при клике на ссылку «О себе» в адресной строке появлялся путь /about, открывалась соответствующая страница, а браузер не запрашивал заново все ресурсы с сервера. React такую навигацию не делает — для этого нужна библиотека маршрутизации.

    Самая популярная библиотека для маршрутизации — React Router. Она связывает URL в адресной строке браузера с React-компонентами и делает навигацию в одностраничных приложениях такой же удобной, как на обычных многостраничных сайтах — с поддержкой кнопок «Назад» и «Вперед», прямых ссылок и закладок.

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

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

    Зачем React-приложениям нужна маршрутизация

    Для начала вспомним, как работают обычные сайты и чем от них отличается React-приложение. Классический многостраничный сайт работает так: пользователь кликает по ссылке, браузер отправляет HTTP-запрос на сервер, сервер формирует HTML-страницу и отдает ее вместе со всеми ресурсами — стилями, скриптами и изображениями. Каждый URL соответствует отдельному HTML-документу на сервере, и при любом переходе по ссылке происходит перезагрузка — браузер заново загружает все полученные файлы и отрисовывает новую страницу с нуля.

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

    React-приложение — это одностраничное приложение, поэтому при первой загрузке браузер получает один HTML-файл и набор JavaScript-файлов. После этого управление интерфейсом полностью берет на себя JavaScript. Все дальнейшие изменения на странице происходят без обращения к серверу за новым HTML — вместо этого React динамически обновляет DOM и перерисовывает только те компоненты, которые действительно изменились. Поскольку полной перезагрузки страницы не происходит, навигация на сайте становится практически мгновенной.

    Но проблема в том, что браузер ничего не знает о ваших «страницах» — для него существует только один адрес, который загружен изначально. Если вы нажмете кнопку «Назад», то вернетесь на предыдущий сайт, а не на предыдущую страницу. А если скопируете ссылку на текущее состояние и попробуете открыть ее в новой вкладке — снова загрузится только главная, потому что URL остался прежним.

    И вот чтобы перемещаться между страницами React-приложения, как раз и нужен механизм маршрутизации. Он связывает URL в адресной строке с тем, что отображается на экране. React эту задачу не решает, потому что его задача — рендерить компоненты. А вот библиотеки вроде React Router как раз на этом специализируются — они отслеживают изменения URL, сопоставляют их с заданными маршрутами и сообщают React, какие компоненты нужно показать.

    Шаг 2
    React Router перехватывает клики по ссылкам и мгновенно меняет URL и содержимое страницы — браузер не перезагружается и не обращается к серверу. Источник: автор статьи 

    Что умеет React Router и как им пользоваться

    В начале 2026 года актуальна седьмая версия React Router, которая предлагает три способа работы с библиотекой: Framework Mode, Data Mode и Declarative Mode.

    Framework Mode — полноценный фреймворк поверх React Router. Он берет на себя не только маршрутизацию, но и рендеринг на сервере (SSR), загрузку данных, оптимизацию сборки и развертывание. По сути, это эволюция Remix — другого фреймворка для React от той же команды разработчиков. До 2024 года это был отдельный проект, но в 2024 году произошло слияние Remix и React Router, и теперь Framework Mode React Router v7 включает в себя все возможности Remix.

    Этот режим предлагает решения для продакшн-приложений: автоматическое разделение кода, предзагрузку данных через loader-функции, оптимизированную гидратацию и встроенные инструменты для деплоя. Однако для новичков в React Framework Mode избыточен, поскольку скрывает детали за абстракциями и требует понимания серверного рендеринга, архитектуры full-stack приложений и lifecycle hooks. Все это сильно усложняет изучение базовых принципов маршрутизации.

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

    Declarative Mode — самый простой и понятный режим. В нем вы только описываете маршруты в JSX с помощью компонентов, оборачиваете приложение в провайдер роутера — и готово. Не нужно настраивать серверный рендеринг или разбираться с загрузкой данных — только базовая маршрутизация. С этого режима начинали все предыдущие версии React Router, и его мы будем использовать далее в статье.

    Шаг 3
    Главная страница библиотеки React Router. Источник

    Собираем сайт‑портфолио и осваиваем базовые концепции роутера

    Теория — это хорошо, но маршрутизацию лучше осваивать на практике. Поэтому далее мы пошагово создадим сайт с такими маршрутами:

    • / — «Главная»;
    • /about — «О себе»;
    • /projects — «Проекты»;
    • /projects/:id — страница конкретного проекта;
    • * — страница 404 для несуществующих маршрутов.

    Чтобы не отвлекаться на дизайн, в первую очередь мы сосредоточимся на концепциях роутинга. Поэтому содержимое сайта до последнего шага будет минимальным — текст и базовая разметка. В конце мы добавим стили и превратим заготовку в полноценный сайт-портфолио. Работать мы будем в редакторе Antigravity, вы же можете использовать VS Code или любой другой инструмент.

    Шаг 1. Создаем проект и устанавливаем React Router

    Для начала создадим новое React-приложение с помощью сборщика Vite. Для этого откройте терминал в редакторе кода и выполните команду:

    npm create vite@latest dev-portfolio -- --template react

    Эта команда создаст папку проекта с именем dev-portfolio. Добавьте ее в редактор, перейдите в нее в терминале и установите базовые зависимости:

    cd dev-portfolio
    npm install

    Теперь установим библиотеку React Router:

    npm install react-router

    Обратите внимание: в седьмой версии библиотеки весь нужный код собран в одном пакете react-router — отдельно устанавливать react-router-dom больше не нужно. Также все компоненты и хуки импортируются напрямую из react-router.

    Запускаем наш проект:

    npm run dev

    Если вы все сделали правильно, в терминале появится сообщение с адресом локального сервера. Откройте этот адрес в браузере — вы увидите страницу с логотипами Vite и React. Это означает, что приложение запущено и готово к работе.

    Шаг 4
    Страница React-приложения, которое создано через Vite. Источник: автор статьи

    Чтобы проверить версии установленных зависимостей, откройте файл package.json в корне проекта и найдите раздел dependencies. Мы будем использовать react: ^19.2.0, react-dom: ^19.2.0 и react-router: ^7.13.0. У вас может быть другая конфигурация.  

    Шаг 5
    Структура проекта с подключенной библиотекой React Router и запущенным локальным сервером. Источник: автор статьи 

    Шаг 2. Добавляем страницы-заглушки

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

    Для этого в папке src создайте папку pages, а внутри нее — следующие четыре файла с расширением .jsx:

    // src/pages/Home.jsx
    export default function Home() {
      return <h1>Главная</h1>;
    }
    
    // src/pages/About.jsx
    export default function About() {
      return <h1>О себе</h1>;
    }
    
    // src/pages/Projects.jsx
    export default function Projects() {
      return <h1>Проекты</h1>;
    }
    
    // src/pages/NotFound.jsx
    export default function NotFound() {
      return <h1>404 — Страница не найдена</h1>;
    }

    Шаг 3. Подключаем роутер и настраиваем маршруты

    Найдите в папке src файл main.jsx и оберните приложение в BrowserRouter:

    import { StrictMode } from 'react'
    import { createRoot } from 'react-dom/client'
    import { BrowserRouter } from 'react-router'
    import App from './App.jsx'
    
    createRoot(document.getElementById('root')).render(
      <StrictMode>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </StrictMode>
    )

    BrowserRouter — это компонент, который дает доступ к функциям маршрутизации во всем приложении. Он использует встроенный браузерный инструмент HTML5 History API для синхронизации интерфейса с текущим URL и позволяет изменять адресную строку без перезагрузки страницы. Для большей ясности представьте BrowserRouter как Wi-Fi-роутер в доме. Один раз подключив его на входе, все устройства внутри получают доступ к интернету. Так же и BrowserRouter — один раз обернув приложение, все компоненты внутри получают доступ к маршрутизации.

    После подключения BrowserRouter в main.jsx откройте файл App.jsx в папке src и настройте маршруты с помощью компонентов Routes и Route. Для этого удалите код, который сборщик Vite сгенерировал автоматически, и замените его на следующий:

    import { Routes, Route } from 'react-router'
    import Home from './pages/Home'
    import About from './pages/About'
    import Projects from './pages/Projects'
    import NotFound from './pages/NotFound'
    
    export default function App() {
      return (
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/projects" element={<Projects />} />
          <Route path="*" element={<NotFound />} />
        </Routes>
      )
    }

    Разберем, что происходит в файле App.jsx:

    • Routes — контейнер для всех маршрутов. Он анализирует текущий URL и отображает только тот компонент Route, путь которого совпадает с адресом.
    • Route — описывает отдельный маршрут. Принимает два ключевых пропа: path — URL-адрес и element — компонент, который нужно показать.
    • path=»*» — специальный маршрут-ловушка, который срабатывает, когда ни один другой маршрут не совпал. Мы его используем для страницы 404.

    На этом этапе вы можете попробовать вручную вводить разные адреса в браузере: localhost:5173/about, localhost:5173/projects или localhost:5173/что-угодно — и вы увидите, как меняется содержимое страницы в зависимости от URL.

    Шаг 6
    Для примера введем http://localhost:5173/projects и попадем на страницу проектов. Пока у нас просто белый фон и текст — это заглушка, так и должно быть. Источник: автор статьи 

    Шаг 4. Делаем навигацию через Link и NavLink

    Вводить URL вручную неудобно, поэтому нам необходимо реализовать меню навигации. Однако важно учитывать, что для ссылок в этом меню мы не можем использовать обычный тег <a> — он вызывает полную перезагрузку страницы, что недопустимо в одностраничных приложениях. Поэтому, чтобы избежать перезагрузки, в React Router предусмотрен компонент Link. Им и воспользуемся.

    В папке src создайте подпапку components, а в ней файл Navbar.jsx:

    import { Link } from 'react-router'
    
    export default function Navbar() {
      return (
        <nav>
          <Link to="/">Главная</Link>
          <Link to="/about">О себе</Link>
          <Link to="/projects">Проекты</Link>
        </nav>
      )
    }

    Чтобы навигация отображалась на всех страницах, добавьте компонент Navbar в файл App.jsx. Расположите его над блоком Routes:

    import { Routes, Route } from 'react-router'
    import Navbar from './components/Navbar'
    import Home from './pages/Home'
    import About from './pages/About'
    import Projects from './pages/Projects'
    import NotFound from './pages/NotFound'
    
    export default function App() {
      return (
        <>
          <Navbar />
          <Routes>
            <Route path="/" element={<Home />} />
            <Route path="/about" element={<About />} />
            <Route path="/projects" element={<Projects />} />
            <Route path="*" element={<NotFound />} />
          </Routes>
        </>
      )
    }

    После добавления навигации в браузере появятся три слипшиеся ссылки вверху страницы, по которым можно кликать и переходить между разделами: 

    Шаг 7
    Источник: автор статьи

    Обычно на сайтах принято визуально выделять активный пункт меню, который соответствует текущей странице. Для этого в React Router есть компонент NavLink — улучшенная версия Link, которая знает, активна ли ссылка в данный момент.

    Здесь есть нюанс: NavLink автоматически добавляет CSS-класс .active к элементу, когда ссылка активна — это поведение работает по умолчанию. Поэтому самый простой способ стилизовать активную ссылку — написать в CSS правило .active { … } и не передавать никаких дополнительных пропсов в NavLink.

    Однако для более тонкой настройки стилей вы можете передавать функцию в проп className. Эта функция будет получать объект с булевым свойством isActive, которое равно true, когда ссылка соответствует текущему URL. На основе этого значения можно динамически применять нужные CSS-классы или инлайн-стили.

    Давайте добавим динамическое применение CSS-класса active через проп className и обновим файл Navbar.jsx:

    import { NavLink } from 'react-router'
    
    export default function Navbar() {
      return (
        <nav>
          <NavLink
            to="/"
            className={({ isActive }) => isActive ? 'active' : ''}
            end
          >
            Главная
          </NavLink>
          <NavLink
            to="/about"
            className={({ isActive }) => isActive ? 'active' : ''}
          >
            О себе
          </NavLink>
          <NavLink
            to="/projects"
            className={({ isActive }) => isActive ? 'active' : ''}
          >
            Проекты
          </NavLink>
        </nav>
      )
    }

    Обратите внимание еще на один момент: для ссылки «Главная» мы добавили проп end. Он указывает, что ссылка считается активной только при точном совпадении пути. Без этого пропа ссылка на / была бы активной на всех страницах, поскольку все пути в приложении начинаются с / (например, /about или /projects).

    Когда вы обновите файл Navbar.jsx, откройте в браузере инспектор элементов, кликните на каждую ссылку в навигации и понаблюдайте, как класс active динамически применяется к активной ссылке и убирается с неактивных:

    Шаг 8
    Источник: автор статьи 

    Шаг 5. Настраиваем динамические маршруты

    Представьте, что со временем в портфолио добавится несколько десятков проектов. Создавать отдельный маршрут для каждого (/projects/1, /projects/2, /projects/3 и так далее) — не лучшая идея. Вам придется прописывать практически одинаковые маршруты для каждого проекта, что усложнит его поддержку. Вместо этого React Router предлагает использовать динамический сегмент пути с параметром :id, который сможет автоматически обрабатывать любой идентификатор проекта.

    Добавьте в App.jsx новый маршрут:

    <Route path="/projects/:id" element={<ProjectDetail />} />

    Двоеточие перед id обозначает динамический параметр маршрута — React Router воспринимает эту часть пути как переменную и сохраняет ее значение для дальнейшего использования в компоненте. Благодаря этому любые URL вида /projects/42 или /projects/my-cool-app будут соответствовать одному маршруту, а значение после /projects/ станет доступно через хук useParams().

    В папке pages создайте файл ProjectDetail.jsx — это будет страница проекта:

    import { useParams } from 'react-router'
    
    export default function ProjectDetail() {
      const { id } = useParams()
    
      return (
        <div>
          <h1>Проект #{id}</h1>
          <p>Здесь будет описание проекта с идентификатором {id}</p>
        </div>
      )
    }

    Теперь обновите файл Projects.jsx и добавьте ссылки на отдельные проекты:

    import { Link } from 'react-router'
    
    const projects = [
      { id: 1, title: 'Интернет-магазин' },
      { id: 2, title: 'Погодный сервис'},
      { id: 3, title: 'Трекер задач' },
    ]
    
    export default function Projects() {
      return (
        <div>
          <h1>Проекты</h1>
          <ul>
            {projects.map(project => (
              <li key={project.id}>
                <Link to={`/projects/${project.id}`}>{project.title}</Link>
              </li>
            ))}
          </ul>
        </div>
      )
    }

    Этот код создаст список кликабельных ссылок на основе массива projects. При клике на любую из них React Router считает значение id из URL (например, 1, 2 или 3) и передает его в компонент ProjectDetail через хук useParams(), где это значение используется для отображения соответствующей информации о проекте.

    Шаг 9
    Для примера перейдем на страницу «Проекты», кликнем на «Трекер задач» и попадем на его страницу с описанием. Источник: автор статьи 

    Шаг 6. Организуем вложенные маршруты и общий лейаут

    Пока наш Navbar живет прямо в файле App.jsx рядом с маршрутами — это работает, но такой подход не получится масштабировать при росте приложения. В реальных проектах разные разделы сайта часто требуют разного лейаута: например, в админ-панели может быть боковое меню, на публичных страницах — минималистичный хедер, а в личном кабинете — уже своя навигация и футер.

    Чтобы это исправить, в React Router предусмотрены вложенные маршруты и компонент Outlet. Родительский маршрут отвечает за общий лейаут с элементами, которые присутствуют на всех страницах раздела (например, навигация и футер). А Outlet — это специальный компонент внутри лейаута, который React Router заменяет содержимым активного дочернего маршрута в зависимости от текущего URL. За счет этого навигация и другие общие элементы остаются на месте, а меняется только та часть страницы, которая находится внутри Outlet.

    Создайте файл Layout.jsx в папке components — это будет общий компонент, который объединяет навигационную панель Navbar и динамическую область для отображения содержимого дочерних маршрутов через Outlet:

    import { Outlet } from 'react-router'
    import Navbar from './Navbar'
    
    export default function Layout() {
      return (
        <>
          <header>
            <Navbar />
          </header>
          <main>
            <Outlet />
          </main>
        </>
      )
    }

    Нам осталось перестроить маршруты в App.jsx:

    import { Routes, Route } from 'react-router'
    import Layout from './components/Layout'
    import Home from './pages/Home'
    import About from './pages/About'
    import Projects from './pages/Projects'
    import ProjectDetail from './pages/ProjectDetail'
    import NotFound from './pages/NotFound'
    
    export default function App() {
      return (
        <Routes>
          <Route element={<Layout />}>
            <Route path="/" element={<Home />} />
            <Route path="/about" element={<About />} />
            <Route path="/projects" element={<Projects />} />
            <Route path="/projects/:id" element={<ProjectDetail />} />
          </Route>
          <Route path="*" element={<NotFound />} />
        </Routes>
      )
    }

    У родительского Route нет пропа path — только element. Это означает, что он не привязан к конкретному адресу и просто оборачивает дочерние маршруты своим лейаутом. Когда пользователь переходит на /about, React Router рендерит Layout, а внутрь Outlet вставляет About. А вот страница 404 намеренно вынесена за пределы Layout, поскольку у нее нет смысла показывать обычную навигацию.

    На этом этапе роутинг готов. У нас есть рабочая навигация, динамические маршруты, вложенные маршруты и страница 404. Этого достаточно для большинства задач, с которыми вы столкнетесь на старте. Однако React Router умеет гораздо больше — у него есть защищенные маршруты, работа с историей браузера, редиректы и многое другое, о чем мы поговрим в другой раз. А на следующем шаге мы просто займемся оформлением, чтобы все напоминало готовый сайт-портфолио.

    Шаг 7. Заполняем страницы и наводим красоту

    В процессе написания этой статьи у нас в редакторе была установлена тема Tokyo Night — это одна из самых популярных цветовых схем среди разработчиков. У нее довольно приятный контраст, поэтому глаза не так сильно устают при долгой работе. Возьмем палитру этой темы за основу для оформления сайта-портфолио.

    Шаг 10
    Цветовая схема Tokyo Night в редакторе Antigravity. Источник: автор статьи

    Для стилизации мы будем использовать CSS-модули — это встроенная возможность React, при которой каждый компонент получает собственный файл стилей с расширением .module.css (например, Home.module.css). При импорте такого файла React автоматически генерирует уникальные имена классов, добавляя к ним хеш — например, вместо .container в браузере будет .Home_container__a1b2c.

    Главное преимущество модулей связано с полной изоляцией стилей: классы работают в пределах компонента и не могут конфликтовать с остальным сайтом. Это позволяет использовать понятные названия вроде .container или .title в любом количестве компонентов и не переживать, что что-то сломается в другом месте.

    Также пришло время заменить текстовые заглушки на что-то более осмысленное. Конечно, для реального портфолио тексты нужно прорабатывать более детально, но для учебного проекта про роутинг мы ограничимся описанием навыков и опыта.

    А в завершении мы сделаем анимированный футер с двумя ниндзя, которые будут играть в волейбол, перебрасывая друг другу логотип React. Это немного оживит интерфейс и покажет, как можно добавлять нестандартные элементы в верстку.

    Чтобы не растягивать статью и не описывать каждый CSS-модуль отдельно — вы можете скачать готовую папку src с полным кодом проекта по этой ссылке и заменить ее у себя в редакторе. После замены перезапустите проект командой npm run dev в терминале и откройте приложение в браузере, чтобы увидеть результат.

    Полезное по теме

    Инструкция

    Поделиться

    Скопировано
    0 комментариев
    Комментарии