Поэтапная миграция

React Router предоставляет мощный инструмент для организации навигации в приложениях на React. Ключевым элементом является компонент <BrowserRouter>, который оборачивает всё приложение и обеспечивает работу истории браузера. Внутри него располагаются маршруты, определяемые с помощью <Routes> и <Route>:

import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './Home';
import About from './About';
import Profile from './Profile';

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/profile/:userId" element={<Profile />} />
      </Routes>
    </BrowserRouter>
  );
}

Каждый маршрут связывает URL с компонентом. Параметры маршрута, например :userId, доступны через хук useParams(), позволяющий динамически получать значения из URL.

Пошаговая миграция с классических решений

  1. Идентификация устаревших маршрутов

    Перед миграцией необходимо определить компоненты, которые используют устаревший способ маршрутизации, например react-router-dom v5 с <Switch> и history.push(). Эти конструкции заменяются на <Routes> и useNavigate().

  2. Обновление корневого роутера

    <BrowserRouter> остаётся базовым элементом, но внутренние маршруты следует переписать с учётом новой структуры:

    • <Switch> заменяется на <Routes>.
    • component в <Route> заменяется на element с JSX.
    • Для вложенных маршрутов используется вложение <Route> внутри родительского <Route>.

    Пример вложенной маршрутизации:

<Routes>
  <Route path="/dashboard" element={<Dashboard />}>
    <Route path="analytics" element={<Analytics />} />
    <Route path="settings" element={<Settings />} />
  </Route>
</Routes>
  1. Переход на хуки навигации

    Методы класса this.props.history.push() заменяются на хук useNavigate():

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

function LoginButton() {
  const navigate = useNavigate();

  const handleLogin = () => {
    // логика авторизации
    navigate('/dashboard');
  };

  return <button onCl ick={handleLogin}>Войти</button>;
}

Динамические маршруты и вложенные пути

В React Router v6 введено упрощённое управление динамическими маршрутами. Использование useParams() позволяет получить параметры URL:

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

function Profile() {
  const { userId } = useParams();

  return <div>Профиль пользователя: {userId}</div>;
}

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

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

function Dashboard() {
  return (
    <div>
      <h2>Панель управления</h2>
      <Outlet />
    </div>
  );
}

Поддержка редиректов и условной маршрутизации

Редиректы в новой версии реализуются с помощью <Navigate>:

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

function PrivateRoute({ isAuthenticated, children }) {
  return isAuthenticated ? children : <Navigate to="/login" replace />;
}

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

Оптимизация и ленивый импорт

Для больших приложений важна оптимизация загрузки компонентов. React Router поддерживает ленивый импорт с помощью React.lazy и Suspense:

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

const Home = lazy(() => import('./Home'));
const About = lazy(() => import('./About'));

function App() {
  return (
    <Suspense fallback={<div>Загрузка...</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </Suspense>
  );
}

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

Управление состоянием маршрутов

Для синхронизации состояния URL с внутренними данными компонентов применяются хуки:

  • useLocation() — получение текущего пути и состояния.
  • useSearchParams() — работа с query-параметрами.
  • useNavigate() — программная навигация.

Пример работы с query-параметрами:

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

function Filter() {
  const [searchParams, setSearchParams] = useSearchParams();
  const category = searchParams.get('category');

  const handleChange = (newCategory) => {
    setSearchParams({ category: newCategory });
  };

  return (
    <div>
      <p>Текущая категория: {category}</p>
      <button onCl ick={() => handleChange('books')}>Книги</button>
    </div>
  );
}

Стратегия поэтапной миграции

  1. Подготовка проекта — установка последней версии react-router-dom, обновление зависимостей.
  2. Замена устаревших компонентов — переход с <Switch> на <Routes>, с component на element.
  3. Переход на хуки — замена методов истории на useNavigate, использование useParams, useLocation.
  4. Внедрение ленивой загрузки — оптимизация большого приложения через React.lazy и Suspense.
  5. Тестирование маршрутов — проверка динамических, вложенных маршрутов, редиректов и query-параметров.
  6. Постепенная интеграция новых компонентов — по мере уверенности в стабильности маршрутов можно переносить остальные части приложения.

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