React роутинг: что спрашивают на интервью и как отвечать уверенно

Разбираем React роутинг для собеседований: client-side navigation, nested routes, params и search params, protected routes, data loading, code splitting, production-ошибки и сильные ответы.

10 марта 2026 г.19 минLexicon Team

Введение

React роутинг на собеседовании редко ограничивается вопросом «что делает Route». Обычно интервьюер через тему маршрутизации проверяет сразу несколько вещей: понимаете ли вы модель SPA-навигации, умеете ли проектировать layout-уровни, различаете ли состояние экрана и состояние компонента, умеете ли работать с загрузкой данных, ошибками и код-сплиттингом.

Из-за этого многие кандидаты отвечают слишком поверхностно: «использовал React Router, настраивал path и navigate». Этого мало. Сильный ответ строится вокруг архитектуры и trade-off’ов. Для базового контекста по клиентской навигации полезно держать рядом подборку junior-вопросов по React.

Больше вопросов в Telegram

Ежедневные разборы и реальные кейсы с интервью.

Подписаться

Что обычно имеют в виду под React роутингом

В React-проектах под роутингом обычно понимают слой, который:

  • сопоставляет URL и экран;
  • определяет вложенные layout-уровни;
  • управляет навигацией между экранами;
  • связывает URL с params, query string и частью состояния приложения;
  • координирует загрузку данных, fallback-состояния и обработку ошибок.

На практике это не только библиотека маршрутизации, но и архитектура экранов. Как только в приложении появляются dashboard-layout, protected sections, модульные страницы, breadcrumbs, deep links и lazy-загрузка, роутинг перестает быть «несколькими Route в одном файле».

Client-side routing против server-side routing

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

Client-side routing в SPA означает, что после первой загрузки документа переходы между экранами происходят без полного reload страницы. Браузер меняет URL, роутер выбирает экран, React обновляет дерево компонентов.

Server-side routing означает, что на каждый переход сервер формирует новую HTML-страницу или новый серверный ответ для целевого URL.

Для React-собеседования важны не определения, а последствия:

  • client-side routing дает быстрые переходы после initial load;
  • server-side routing помогает с первой загрузкой, SEO и серверным контролем данных;
  • в клиентской навигации надо отдельно продумывать loading, data fetching, 404 и защиту приватных экранов;
  • в server-first системах часть задач маршрутизации уходит в платформу, но не исчезает архитектурно.

Хороший кандидат явно проговаривает, что client-side routing не отменяет серверную ответственность за доступ к данным. Скрыть route на клиенте недостаточно, если API все равно отдает защищенную информацию.

Архитектура роутинга: как мыслят зрелые команды

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

Какие слои обычно есть

  1. Корневой shell. Отвечает за app-wide providers, тему, глобальные boundary, общую навигацию.

  2. Layout routes. Описывают общую рамку для группы экранов: sidebar, header, breadcrumbs, access policy.

  3. Screen routes. Это конкретные страницы или крупные экранные сценарии.

  4. Widget-level components. Обычные React-компоненты внутри страницы, которые не должны знать о роутере больше, чем нужно.

Поток данных и управления

Нормальный поток выглядит так:

  1. URL приходит в роутер.
  2. Роутер выбирает цепочку layout + page компонентов.
  3. На route-уровне определяется, какие данные и проверки нужны.
  4. Экран получает params, search params и загрузочные данные.
  5. Внутренние виджеты уже работают как обычные компоненты.

Узкие места начинаются, когда роутер знает слишком мало или слишком много.

Если логика авторизации, фильтров, табов, прелоадов и аналитики размазана по виджетам, приложение становится хрупким. Если же в конфиг роутера запихнули все подряд, он превращается в монолитную карту, которую страшно менять.

Нормальная деградация обычно выглядит так:

  • route-level loading не блокирует весь shell;
  • локальная ошибка не валит все приложение;
  • 404 и access denied имеют отдельные ветки;
  • lazy routes загружаются по мере необходимости.

Для этого полезно понимать, где ставятся error boundaries и как они соотносятся с route-уровнем.

Базовый пример: nested routes и layout

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

import {
  createBrowserRouter,
  Navigate,
  Outlet,
  RouterProvider,
} from "react-router-dom";

function AppLayout() {
  return (
    <div className="app-shell">
      <header>Lexicon</header>
      <main>
        <Outlet />
      </main>
    </div>
  );
}

function DashboardLayout() {
  return (
    <section className="dashboard">
      <aside>Sidebar</aside>
      <div className="content">
        <Outlet />
      </div>
    </section>
  );
}

const router = createBrowserRouter([
  {
    path: "/",
    element: <AppLayout />,
    children: [
      { index: true, element: <HomePage /> },
      {
        path: "dashboard",
        element: <DashboardLayout />,
        children: [
          { index: true, element: <Navigate to="analytics" replace /> },
          { path: "analytics", element: <AnalyticsPage /> },
          { path: "settings", element: <SettingsPage /> },
        ],
      },
      { path: "*", element: <NotFoundPage /> },
    ],
  },
]);

export function AppRouter() {
  return <RouterProvider router={router} />;
}

Что здесь важно объяснить:

  • Outlet задает точку вложенного рендера;
  • layout routes позволяют не дублировать shell;
  • index route полезен для дефолтного дочернего экрана;
  • wildcard-ветка нужна для 404;
  • редирект внутри вложенного layout лучше держать явным, а не размазывать по useEffect.

Если кандидат умеет объяснить именно это, а не только синтаксис, ответ уже выглядит уровнем выше.

Params, search params и состояние URL

Очень частый блок вопросов: что держать в path params, что в query string, а что в локальном state.

Path params

Их используют, когда значение определяет ресурс или экран:

  • /users/:id
  • /orders/:orderId
  • /courses/:slug/lessons/:lessonId

Search params

Они подходят для экранного состояния, которое:

  • должно переживать refresh;
  • должно шариться ссылкой;
  • влияет на представление данных, а не на сам ресурс.

Типичные примеры:

  • ?page=3
  • ?sort=price_desc
  • ?tab=activity
  • ?query=react

Что часто ломают

Кандидаты нередко держат фильтры только в local state. В коротком демо это нормально, но в production пользователь теряет состояние после refresh, не может поделиться ссылкой и получает странное поведение back/forward navigation.

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

Пример синхронизации search params:

import { useSearchParams } from "react-router-dom";

function UsersPage() {
  const [searchParams, setSearchParams] = useSearchParams();

  const page = Number(searchParams.get("page") ?? "1");
  const query = searchParams.get("query") ?? "";

  function updateQuery(nextQuery: string) {
    const next = new URLSearchParams(searchParams);

    if (nextQuery) {
      next.set("query", nextQuery);
      next.set("page", "1");
    } else {
      next.delete("query");
      next.delete("page");
    }

    setSearchParams(next);
  }

  return (
    <section>
      <SearchBox defaultValue={query} onSearch={updateQuery} />
      <UsersTable page={page} query={query} />
    </section>
  );
}

Тут важно не только уметь читать params, но и объяснить, почему page сбрасывается при изменении поиска: это уже разговор на языке продуктовой логики, а не API.

Таблица: какие задачи решать каким уровнем роутинга

СценарийLocal stateSearch paramsPath paramsRoute-level layout
Открыт ли локальный dropdownДаНетНетНет
Активная страница пагинацииИногдаДаНетНет
Текущий пользователь /users/:idНетНетДаНет
Вкладка внутри экранного сценарияИногдаЧасто даРедкоИногда
Общая рамка dashboardНетНетНетДа
Фильтры, которыми делятся ссылкойПлохоДаНетНет
Защита приватного разделаНетНетНетДа

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

Protected routes: где кандидат чаще всего ошибается

На словах почти все говорят: «если пользователь не авторизован, делаем redirect на login». Этого мало.

Protected route в production должен учитывать:

  • состояние loading, пока мы не знаем текущего пользователя;
  • различие между unauthenticated и forbidden;
  • возврат пользователя на исходный URL после логина;
  • ситуацию, когда токен протух в процессе навигации;
  • то, что клиентский guard сам по себе не защищает серверные данные.

На практике auth-состояние для таких сценариев часто поднимают через контекст или отдельный session-layer. Поэтому полезно понимать не только роутер, но и когда действительно нужен React Context API.

Базовый паттерн:

import { Navigate, Outlet, useLocation } from "react-router-dom";

function ProtectedRoute() {
  const location = useLocation();
  const { user, isLoading } = useAuth();

  if (isLoading) {
    return <RouteSkeleton />;
  }

  if (!user) {
    return (
      <Navigate
        to="/login"
        replace
        state={{ from: location.pathname + location.search }}
      />
    );
  }

  return <Outlet />;
}

Хороший комментарий к этому примеру:

  • нельзя редиректить до завершения auth-check, иначе будет route flicker;
  • state.from нужен для возврата после логина;
  • replace помогает не засорять history;
  • серверная авторизация все равно обязательна.

Если кандидат проговаривает хотя бы половину этих пунктов, это обычно заметно отличает его от ответа уровня «просто проверяю токен в localStorage».

Data loading и экранные границы

Когда разговор заходит глубже, интервьюер часто спрашивает не про сам роутер, а про то, где грузить данные: в компоненте страницы, в route-слое или в кастомных хуках.

Здесь нет одного универсального ответа, но зрелая аргументация выглядит так:

  • route-level loading хорош для данных, без которых экран нельзя собрать;
  • widget-level loading хорош для вторичных блоков, которые не должны блокировать весь route;
  • layout-level loading оправдан, когда данные общие для нескольких дочерних экранов;
  • критично не дублировать fetch одних и тех же данных на каждом переходе между соседними route.

Это напрямую связано с Suspense, error boundary и стоимостью лишних ререндеров при навигации.

Production pitfalls: что реально ломается

Ошибка 1. Route guard редиректит раньше, чем завершилась проверка пользователя

Симптомы:

  • при refresh приватного экрана пользователя бросает на login и сразу возвращает обратно;
  • в логах фронтенда видно двойную навигацию;
  • аналитика считает лишние page views.

Последствия:

  • route flicker;
  • нестабильный UX;
  • сложные баги с сохранением intended URL.

Как обнаружить заранее:

  • смотреть цепочки navigation в devtools;
  • проверять поведение при медленном ответе /me;
  • тестировать refresh на приватной странице.

Ошибка 2. Фильтры и пагинация не синхронизированы с URL

Симптомы:

  • пользователь делится ссылкой, а коллега видит другой экран;
  • после refresh все фильтры сбрасываются;
  • кнопки back/forward ведут себя нелогично.

Последствия:

  • ломается deep linking;
  • растет число повторных действий пользователя;
  • усложняется поддержка аналитики и QA.

Как исправить:

  • выносить экранное состояние в search params;
  • хранить в URL только то, что реально определяет экран;
  • не смешивать временный UI-state и sharable state.

Ошибка 3. Каждый route повторно грузит одни и те же данные

Симптомы:

  • при переходе между соседними вкладками dashboard заново дергается один и тот же профиль;
  • растут latency и network cost;
  • пользователь видит постоянные skeleton на каждом клике.

Последствия:

  • лишняя нагрузка на API;
  • замедление навигации;
  • деградация perceived performance.

Как предотвратить:

  • поднимать общие данные на layout-level;
  • использовать кэширование и нормальную стратегию invalidation;
  • разделять критические и вторичные запросы.

Разбор производительности

Сам по себе роутинг редко bottleneck. Обычно узкие места появляются рядом:

  • слишком тяжелые route-компоненты;
  • повторный data fetching на каждой навигации;
  • неудачный code splitting;
  • глобальные provider'ы, которые ререндерят весь shell;
  • избыточная синхронизация state и URL.

Когда оптимизация оправдана:

  • route chunk весит слишком много и мешает первой интерактивности;
  • переходы между крупными экранами сопровождаются заметным layout shift;
  • на каждый route-change летят дублирующие запросы;
  • shell ререндерится целиком из-за изменения локального состояния страницы.

Когда optimization premature:

  • у приложения 5 простых страниц;
  • навигация и так мгновенная;
  • вы еще не измеряли ни bundle, ни network, ни route transitions.

Полезный инженерный ответ здесь звучит так: я бы профилировал переходы, смотрел размер чанков, количество повторных запросов, время route-to-interactive и только потом решал, нужен ли aggressive code splitting или переразбиение layout-уровней. По смежной теме помогает помнить разбор React rendering.

Если разговор уходит в оптимизацию глубже, логично связать routing с типичными вопросами по React performance, потому что route transition почти всегда упирается не в сам роутер, а в лишние ререндеры, тяжелые провайдеры и дублирующий fetch.

Прокачай React за 7 дней

20 вопросов и разборов по React Hooks.

Начать

Практики, которые реально работают

Держите layout-уровни явными

Root layout, auth layout, dashboard layout и public layout лучше оформлять отдельно. Это уменьшает дублирование и упрощает доступ, breadcrumbs и общие данные.

Храните sharable screen state в URL

Поиск, page, sort, tab и фильтры, влияющие на представление списка, обычно должны жить в search params.

Ставьте route-level error handling осознанно

Если ошибка одного виджета не должна валить всю страницу, не поднимайте boundary слишком высоко. Если же без данных route экран бессмысленен, boundary на уровне route оправдан.

Не делайте роутер единственным местом всей бизнес-логики

Роутинг должен координировать экран, а не хранить всю логику продукта. Как только конфиг роутера становится местом, где живет половина приложения, сопровождение дорожает.

Тестируйте не только happy path

Нужны как минимум такие сценарии:

  • переход на неизвестный URL;
  • refresh приватного route;
  • возврат после логина на исходный экран;
  • навигация back/forward с search params;
  • медленный route data fetch;
  • отказ одного экрана без падения всего shell.

Частые ошибки

Путать path params и search params

Если page=3 или sort=asc запихивают в path без причины, URL становится хуже масштабируемым. Если userId уезжает в query string, маршрут теряет четкую модель ресурса.

Делать редиректы через useEffect, когда можно декларативно

Декларативный redirect в route-дереве или в guard-компоненте обычно проще, чем императивная навигация после mount.

Хранить URL-состояние и local state без стратегии синхронизации

После этого одни и те же фильтры живут в двух местах, а источник истины непонятен.

Недооценивать 404 и route-level ошибки

На маленьком pet-проекте это не видно, но в production отсутствие отдельного 404 и fallback-стратегии делает навигацию хрупкой и плохо диагностируемой.

Как отвечать на интервью

Хороший каркас ответа на вопрос «что вы знаете про React роутинг?» обычно такой:

  1. Роутинг в React это не просто Route, а слой сопоставления URL, layout-уровней, навигации и части экранного состояния.
  2. В SPA используется client-side navigation без полной перезагрузки документа, но это не отменяет серверную ответственность за доступ к данным.
  3. Важные темы на практике: nested routes, layout routes, params и search params, protected routes, 404, loading/error handling и code splitting.
  4. URL должен хранить состояние, которое определяет экран и должно переживать refresh или шариться ссылкой.
  5. Основные ошибки в production: ранние редиректы, дублирование fetch, потеря state при навигации и отсутствие стратегии для loading/error.

Если спрашивают глубже, можно дать быстрые формулировки:

  • nested routes нужны для layout composition и уменьшения дублирования;
  • protected route это не только redirect, но и корректная обработка auth-loading и forbidden state;
  • search params хороши для фильтров, сортировки, табов и пагинации;
  • route-level data loading уместен, когда без данных нельзя собрать экран;
  • lazy routes полезны, когда вы реально боретесь за initial bundle и route transition cost.

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

Подготовься к React-интервью на реальных сценариях маршрутизации

Разберем routing, hooks, ререндеры, ошибки и архитектурные trade-off'ы в формате mock-интервью с разбором сильных и слабых ответов.

Начать тренировку

FAQ

Что важнее на интервью: знать API роутера или понимать архитектуру

Архитектура. Синтаксис Route, Link и navigate можно быстро вспомнить, а вот объяснить, где хранить screen state и как строить protected layout, без понимания модели не получится.

Когда фильтр надо класть в URL

Когда он определяет экран, должен переживать refresh, участвует в deep link и нужен для back/forward navigation.

Достаточно ли protected route на клиенте

Нет. Клиентский guard управляет UX и навигацией, но не заменяет серверную проверку доступа к данным.

Почему nested routes любят на собеседованиях

Потому что через них быстро видно, умеет ли кандидат мыслить layout-уровнями и понимает ли, как не дублировать shell и общую логику по страницам.

Что чаще всего недооценивают в роутинге

404, loading/error states, возврат после логина, синхронизацию search params и влияние роутинга на data fetching и bundle size.

Итоги

React роутинг на интервью это вопрос не про библиотеку, а про экранную архитектуру. Интервьюер хочет понять, умеете ли вы разложить ответственность между URL, route layout, page-компонентом и локальным UI-состоянием.

Если коротко, зрелое понимание темы выглядит так: URL описывает экранный контракт, nested routes собирают layout без дублирования, protected routes управляют UX, но не подменяют серверную безопасность, а loading/error/code splitting проектируются на route-уровне осознанно. Именно такой ответ обычно звучит как опыт работы с production-приложением, а не как пересказ документации.

Больше вопросов в Telegram

Ежедневные разборы и реальные кейсы с интервью.

Подписаться

Автор

Lexicon Team

Читайте также