react-router 是 React 应用路由管理的核心库,提供了路由匹配和导航的基础逻辑。react-router-dom 和 react-router-native 分别是针对 Web 浏览器环境和 React Native 移动环境的具体实现,它们依赖并扩展了核心包的功能。@reach/router 是早期的路由方案,现已合并至 react-router v6 并标记为废弃,不再建议在新项目中使用。
在 React 生态系统中,路由管理是构建单页应用(SPA)和移动应用的基石。react-router 系列包提供了从核心逻辑到环境适配的完整解决方案,但不同包之间的职责划分常常让开发者感到困惑。特别是随着 @reach/router 的合并与废弃,选型变得更加关键。本文将深入对比这四个包的技术细节,帮助你在架构设计中做出正确决策。
理解这些包的关系是选型的第一步。它们不是平行关系,而是层级关系。
react-router 是核心库。
useNavigate)和逻辑。// react-router: 核心钩子
import { useLocation, useNavigate } from 'react-router';
// 仅包含逻辑,无 BrowserRouter 等环境组件
react-router-dom 是 Web 环境实现。
react-router。BrowserRouter、HashRouter、Link 等 DOM 特定组件。// react-router-dom: Web 环境
import { BrowserRouter, Link } from 'react-router-dom';
// 包含核心功能 + 浏览器历史 API 封装
react-router-native 是移动端环境实现。
react-router。NativeRouter、Link 等 React Native 特定组件。// react-router-native: 原生环境
import { NativeRouter, Link } from 'react-router-native';
// 包含核心功能 + 原生导航栈封装
@reach/router 是历史遗留包。
react-router 的竞争者,后合并入 v6。// @reach/router: 已废弃 (Legacy)
import { Router, Link } from '@reach/router';
// 不再接收更新,存在潜在兼容性风险
路由的核心是监听地址变化并渲染组件,但 Web 和 Native 的地址管理机制完全不同。
react-router-dom 使用浏览器历史 API。
window.history 实现导航。BrowserRouter (HTML5 History) 和 HashRouter。// react-router-dom: 浏览器历史
import { BrowserRouter, Routes, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
</Routes>
</BrowserRouter>
);
}
react-router-native 使用原生导航栈。
// react-router-native: 原生栈
import { NativeRouter, Routes, Route } from 'react-router-native';
function App() {
return (
<NativeRouter>
<Routes>
<Route path="/" element={<Home />} />
</Routes>
</NativeRouter>
);
}
react-router 不处理环境细节。
Routes 和 Route 等通用组件。// react-router: 通用组件 (需配合环境包)
import { Routes, Route } from 'react-router';
// 单独使用无法工作,缺少历史监听器
@reach/router 使用自有历史实现。
react-router v6 取代。// @reach/router: 旧版实现
import { Router } from '@reach/router';
// 旧版 API,不再兼容新生态工具
在实际编码中,链接和编程式导航是最常用的功能。不同包的实现细节直接影响代码迁移成本。
react-router-dom 提供标准 Link 组件。
<a> 标签,支持 SEO 和右键打开新标签。useNavigate 钩子。// react-router-dom: Web 链接
import { Link, useNavigate } from 'react-router-dom';
function Nav() {
const navigate = useNavigate();
return (
<>
<Link to="/about">About</Link>
<button onClick={() => navigate('/home')}>Go Home</button>
</>
);
}
react-router-native 提供原生 Link 组件。
TouchableOpacity 或其他原生触摸组件。useNavigate,但行为适配原生栈。// react-router-native: 原生链接
import { Link, useNavigate } from 'react-router-native';
function Nav() {
const navigate = useNavigate();
return (
<>
<Link to="/about">About</Link>
<button onPress={() => navigate('/home')}>Go Home</button>
</>
);
}
react-router 仅提供钩子。
Link 组件,因为不知道如何渲染链接。useNavigate 等逻辑钩子。// react-router: 仅逻辑
import { useNavigate } from 'react-router';
// 无 Link 组件,需自行实现或依赖环境包
@reach/router 使用旧版 API。
navigate 函数而非钩子。Link 组件 API 类似,但底层实现不同。// @reach/router: 旧版导航
import { Link, navigate } from '@reach/router';
function Nav() {
return (
<>
<Link to="/about">About</Link>
<button onClick={() => navigate('/home')}>Go Home</button>
</>
);
}
@reach/router 的状态是架构决策中的关键风险点。
@reach/router 已正式废弃。
react-router v6。// ❌ 不推荐:旧项目代码
import { Router } from '@reach/router';
// ✅ 推荐:迁移后代码
import { BrowserRouter } from 'react-router-dom';
迁移核心变化。
Router 替换为 BrowserRouter 或 NativeRouter。navigate 函数替换为 useNavigate 钩子。// 迁移对比
// 旧:@reach/router
<Route path="users/:id" component={User} />
// 新:react-router-dom v6
<Route path="users/:id" element={<User />} />
| 特性 | react-router | react-router-dom | react-router-native | @reach/router |
|---|---|---|---|---|
| 定位 | 核心逻辑层 | Web 环境实现 | 原生环境实现 | 已废弃的旧方案 |
| 适用平台 | 任意 (需自定义) | 浏览器 (Web) | iOS / Android (React Native) | 旧 Web 项目 |
| 路由组件 | Routes, Route | BrowserRouter, HashRouter | NativeRouter | Router |
| 导航组件 | 无 | Link, NavLink | Link | Link |
| 导航钩子 | useNavigate, useLocation | 同左 (继承) | 同左 (继承) | navigate 函数 |
| 维护状态 | ✅ 活跃维护 | ✅ 活跃维护 | ✅ 活跃维护 | ❌ 已废弃 |
react-router-dom 是 Web 开发的标准答案。
除非你有极其特殊的自定义需求,否则不要直接使用 react-router 核心包。react-router-dom 提供了所有必要的功能,且与 React 生态工具链集成最好。对于新项目,它是唯一推荐的选择。
react-router-native 是移动开发的必经之路。
在 React Native 中,不要尝试复用 Web 的路由组件。原生导航栈的行为(如手势返回、动画)与 Web 历史完全不同。使用专用包能确保用户体验符合平台规范。
彻底告别 @reach/router。
如果你正在维护旧项目,制定迁移计划是当务之急。react-router v6 已经吸收了 Reach Router 的优点,继续分离维护没有意义。迁移成本可控,但长期收益巨大。
最终结论:Web 选 react-router-dom,移动端选 react-router-native,核心包 react-router 仅作为依赖存在,@reach/router 请立即停用。
仅在你需要构建自定义路由环境或非标准平台适配时使用。对于绝大多数 Web 或移动端应用,应直接选择 react-router-dom 或 react-router-native,因为它们包含了核心包的所有功能并添加了环境必要的组件。
这是构建 Web 应用的标准选择。如果你正在开发运行在浏览器中的 React 网站、单页应用(SPA)或混合应用,此包提供了 BrowserRouter、Link 等必要的 DOM 操作组件,是大多数前端项目的默认选项。
不要在新项目中使用此包。它已正式废弃,功能已合并到 react-router v6 中。继续使用将面临缺乏维护和安全更新的风险,建议立即迁移到 react-router-dom。
专用于 React Native 移动应用开发。如果你需要为 iOS 或 Android 构建原生界面,此包提供了 NativeRouter 和适配触摸导航的 Link 组件,能正确处理原生栈导航行为。
react-router is the primary package in the React Router project.
npm i react-router