版本差异
v6 是一次重大更新,目标是简化 API 、 提升性能,并更好的适配 React 新特性(如 <Suspense> )。而 v7 像是 v6 的优化版,重点是提升 React 18 的兼容性,并简化使用体验。
一、 React Router v5 到 v6 的主要区别
1.路由配置模式:从 component 到 element
- v5 使用
component属性传递组件(需配合render或children处理参数)<Route path="/user" component={User} /> - v6 强制使用
element属性直接传递 JSX 元素(无需额外的处理参数,通过useParams等 hook 获取参数)<Route path="/user" element={<User />} />
2.嵌套路由: <Outlet> 替代隐式渲染
-
v5 处理嵌套路由需要手动通过
this.props.children或render属性渲染子路由,结构复杂// 父组件
<Route
path="/parent"
render={() => (
<Parent>
<Route path="child" component={Child} />
</Parent>
)}
/> -
v6 则通过
<Outlet />占位符明确子路由渲染位置,结构更清晰// 父组件
function Parent() {
return (
<div>
<div>
<h1>父级</h1>
<Outlet />
</div>
</div>
);
}
// 路由配置
<Route path="/parent" element={<Parent />}>
<Route path="child" element={<Child />} />
</Route>;
3. 路由匹配: <Routes> 代替 <Switch>
- v5 使用
<Switch>按顺序匹配第一个符合的路由,需手动添加exact避免误匹配<Switch>
<Route path="/" component={Home} exact />
<Route path="/about" component={About} />
</Switch> - v6 用
<Routes>自动基于 **最长路径匹配 ( 无需exact),且支持相对路径(子路径相对于父路由)<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="parent" element={<Parent />}>
<Route path="child" element={<Child />} />
</Route>
</Routes>
4. 导航 API : useHistory() ➞ useNavigate()
- v5 通过
useHistory()获取 history 对象,调用push()/replace()/goBac()const history = useHistory();
history.push('/new-path'); - v6 使用
useNavigate()提供更直观的导航方式const navigate = useNavigate();
navigate('/new-path'); // 跳转
navigate('/new-path', { replace: true }); // 替换当前记录
navigate(-1); // 回退,等价于 goBack
5. <Suspense> 集成
v6 版本支持原生的 React 的 <Suspense> ,可包裹路由组件实现懒加载。
<Suspense fallback={<Loading/>}>
<Routes>
<Route path="/data" element={<DataComponent />}/>
</Route>
</Suspense>
需配合支持 <Suspense> 的数据加载方案,如 React Query 或 React Router 的 loader 函数。
6. 路由重定向
v5 使用 <Redirect> ,而在 v6 中推荐使用 <Navigate> 。
// v5
<Redirect to="/Home" />
// v6
<Navigate to="/home" />
7. 包大小
- v5 : 约 20.8K(未压缩), 7.3K (压缩后)
- v6 : 约 10.8K(未压缩), 3.8K (压缩后)
8. 路由配置方式:从 “分散”到“集中”
- v5 : 通常在 JSX 中直接写
<Route>分散配置 - V6 : 推荐使用
createBrowserRouter()等 API 集中处理路由配置(数组形式),再通过RouterProvider注入,更利于大型项目的维护
// v6 集中处理
const router = createBrowserRouter({
{path: '/', element: <Home />},
{
path: '/user',
element: <User />,
children: [
{
path: 'profile',
element: <Profile />
}
]
}
});
function App(){
return <RouterProvider router={router}>
}
```
### 9. 改进
- 移除了 `activeClassName` 和 `activeStyle`
- 移除 `withRouter` 高阶组件,推荐使用 `useLocation`/`useParams` 等 hook
- 引入了 `useRoutes` 代替 `react-router-config`
- 路径参数支持更灵活的正则匹配,如 `path="/user/:id(\\d+)"` 限制为数字
## 二、 [React Router] v6 ➞ v7 的主要区别
v7 采用新架构,使用 `Router Modules` + `Fetcher Pattern` ,低成对齐(借鉴) Remix
### 1.强制 `element` 属性,移除 `component`
- v6 中虽然推荐使用 `element` ,但仍保留 `component` 属性(可能引发警告)
- v7 中完全移除了 `component` ,仅支持 `element` ,强制统一 API
```jsx
{
/** v7 不再支持此写法 */
}
<Route path="/user" component={User} />;
{
/** 必须使用 element */
}
<Route path="/about" element={<User />} />;
2. 深度集成了 React 18 并发特性
v7 优化了对 React 18 并发模式( Concurrent Mode )的支持,导航时更平滑:
- 支持 中断渲染 :若用户在导航过程中触发新导航, React 18 可中断当前渲染,优先处理新请求
- 更好的 数据加载协调 : 与
useAsyncValue或useTransition配合,减少加载闪烁
3. 新增 useNavigationTypeHook
用于判断当前导航类型( POP/PUSH/REPLACE )帮助区分前进/回退/替换操作
import { useNavigateType } from 'react-route';
// 'POP' 表示前进
const navigateType = useNavigationType();
4. 优化服务器渲染 ( SSR )
v7 改进了 SSR 支持,减少 hydration 阶段的错误:
- 路由配置在服务端和客户端更一致,避免因异步加载导致的
hydration不匹配 - 更高的
StaticRouter支持,适配Next.js等框架的静态生成
5. 数据获取与加载
- v6 : 基础
loader/action支持 - v7 : 引入
Route Module架构,每个路由封装其 UI 和loader、action、meta等
export const loader = async () => await fetch('/api/data');
6. 懒加载能力
- v6 : 有限
React.lazy - v7 : 更强,路由本身可以按需懒加载 (模块级
split)
7. 刷新策略
- v6 :
useNavigate、navigate(0)等 - v7 :
router.revalidate()主动刷新能力
8. 错误处理
- v6 : 基础错误处理
- v7 : 支持每个路由自定义
ErrorElement(出错不影响其他的 UI)
// v7 路由示例
const route = {
path: '/user/:id',
element: <User />,
errorElement: <Errorpage />,
};
function Post() {
/** 获取路由相关错误 */
const error = useRouteError();
if (error) {
return <div>错误 : {error.message} </div>;
}
}
9. 数据缓存与重新验证
- v6 : 基础
loader()每次执行 - v7 : 实验性支持缓存/重新验证机制(Revalidation)
// v7 数据加载 (进入路由前自动执行)
const router = createBrowserRouter([
{
path: '/posts/:id',
element: <Post />,
loader: async ({ params }) => {
// 加载数据
const res = await fetch(`/api/posts/${params.id}`);
return res.json();
},
action: async ({ request }) => {
// 处理提交(如表单)
const fromData = await request.formData();
return await updatePost(formData);
},
},
]);
// 组件中获取加载的数据
function Post() {
// v7 稳定钩子
const post = useLoaderData();
return <div>{post.title}</div>;
}
10. 新性能
shouldRevalidate: 路由自定义是否重新请求loader,优化性能Fetcher模 : 提供统一的数据获取、提交、错误处理体验
11. 其他细节调整
useParams性能优化 : 避免不必要的重新渲染( v6 中参数可能触发父组件重渲染, v7 优化了依赖追踪)- 更严格的 TypeScript 类型 : 类型定义更精确,减少类型推断错误
- **移除试验性 API ** : 如 v6 中部分未稳定的功能被正式废弃或移除
三、 对比表格
| 特性 | v5 | v6 | v7 |
|---|---|---|---|
| 路由配置属性 | component | element (推荐) | 强制 element |
| 嵌套路由 | 手动 children/render | <Outlet /> 占位符 | 同左,进一步优化类型 |
| 路由匹配 | <Switch> + exact | <Routes> + 最长路径匹配 | 同左,优化 SSR |
| 导航 API | useHistory() | useNavigate() | 同左,新增 useNavigationType() |
| React 18 支持 | 部分支持 | 基础支持 | 深度集成并发模式 |
| SSR 体验 | 一般 | 改进 | 进一步优化 hydration |