React Router предоставляет мощный инструмент для организации маршрутизации в приложениях на React, но при работе с различными версиями библиотеки и компонентами необходимо учитывать вопросы совместимости. Особенно это важно при интеграции с внешними компонентами, библиотеками состояния или пользовательскими хук-компонентами.
1. Компоненты <Routes> и
<Route>
Начиная с версии React Router 6, <Switch> был
заменён на <Routes>. Это изменение напрямую влияет на
совместимость с более старыми компонентами. Основные моменты:
<Routes> ожидает в качестве дочерних элементов
исключительно <Route>. Любые другие компоненты внутри
могут вызвать ошибку рендера.component больше не поддерживается;
используется element, которому передаётся JSX:<Route path="/home" element={<Home />} />
component в element:const RouteWrapper = ({ component: Component }) => <Component />;
2. Навигационные компоненты (<Link> и
<NavLink>)
<Link> и <NavLink> остаются
совместимыми между версиями 5 и 6, однако стоит учитывать:
to должен быть строкой или объектом с полями
pathname, search и hash.activeClassName в
<NavLink> были заменены на функцию
className, возвращающую строку в зависимости от состояния
isActive.<NavLink to="/about" className={({ isActive }) => isActive ? "active" : ""}>
About
</NavLink>
React Router активно использует контекст для передачи текущего маршрута. Основные хуки:
useNavigate() для программной навигации.useParams() для получения динамических параметров
маршрута.useLocation() для доступа к текущему пути и параметрам
поиска.useMatch() для проверки совпадения с маршрутом.Особенности совместимости:
<Routes> или <Router>. Вне этих
контейнеров они вызовут ошибку
useNavigate() may be used only in the context of a Router.RouterContext.Для UI-библиотек (Material-UI, Ant Design) и собственных компонентных наборов важно соблюдать следующие принципы:
<Link> внутри кнопок
или меню, должны корректно передавать ref и другие
пропсы.<Route> и <Routes>, чтобы анимация
не ломала контекст маршрутизации.import { motion } from "framer-motion";
const AnimatedRoute = ({ element }) => (
<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
{element}
</motion.div>
);
В React Router 6 вложенные маршруты стали более строго типизированными:
<Route> должен содержать дочерние
<Route> внутри, иначе вложенные маршруты не будут
работать.index используется для указания маршрута по
умолчанию внутри группы маршрутов.exact,
следует помнить, что в версии 6 поведение exact теперь
встроено по умолчанию.<Route path="dashboard" element={<Dashboard />}>
<Route index element={<Overview />} />
<Route path="stats" element={<Stats />} />
</Route>
React Router поддерживает SSR через
StaticRouter, что важно для Next.js, Remix или
собственного серверного решения. Основные моменты:
StaticRouter не изменяет URL на клиенте; все маршруты
должны быть рассчитаны заранее.useNavigate() и
useLocation() требуется передача context и
location в StaticRouter.<Link> внутри SSR,
должны быть обёрнуты в <StaticRouter> на сервере и
<BrowserRouter> на клиенте.<StaticRouter location={req.url} context={{}}>
<App />
</StaticRouter>
component → elementrender → использовать JSX внутри
elementexact → больше не нужен для точного совпаденияSwitch → <Routes>Переход на современную версию требует рефакторинга компонентов, иначе возможны ошибки совместимости, особенно при работе с динамическими маршрутами и хуками.
<Routes> как родительский
контейнер для <Route>.<Router>-компонентов.StaticRouter с корректным
контекстом.Эти правила совместимости позволяют создавать сложные многоуровневые приложения с React Router, избегать конфликтов контекста и ошибок рендера, а также обеспечивают плавный переход между версиями библиотеки.