React Router
核心判断
- React Router 的核心不是“页面跳转 API”,而是把 URL 当成应用状态,把路由树当成 UI 结构,把导航当成状态切换。
- 学 React Router 的主线应从三层递进:先理解 URL 如何映射视图,再理解路由如何组织布局与数据,最后理解路由如何成为代码分割、SSR、微前端等架构边界。
- 现代 React Router 的关键变化是“数据路由”:路由不只决定渲染哪个组件,也开始承载数据加载、提交、错误处理与导航状态。
这个主题要回答的问题
- React Router 解决的核心问题是什么?
- 为什么说 URL、路由树、UI 布局树应放在同一个模型里理解?
- 什么时候使用组件式路由,什么时候使用数据路由?
- params、search、location state 分别适合表达哪类状态?
- React Router 如何进入更大的前端架构问题,例如懒加载、SSR、微前端和渐进式集成?
主题结构
1. 路由的基础模型:URL 是可分享的应用状态
- URL 状态化:React Router 的第一层心智模型,是把 pathname、search、hash 与 history 都看作可导航、可回退、可分享的状态来源。
- 路由历史模式:BrowserRouter、HashRouter、MemoryRouter 的差异,本质是“导航状态存在哪里、谁负责响应变化”。
- 可分享、可刷新后恢复的状态优先放进 URL;只在本次跳转中临时使用的上下文,才适合放进 location state。
2. 路由树的组织模型:路由结构映射 UI 布局结构
- 路由树即布局树:父路由负责稳定布局,子路由通过
<Outlet />填充变化区域,嵌套路由因此成为组织页面结构的方式。 - index 路由、动态路由、通配路由、布局路由分别处理默认内容、资源详情、兜底匹配与共享布局。
- 当嵌套路由和 UI 结构不一致时,路由表会从“页面结构描述”退化成“跳转配置堆”。
3. 导航模型:声明式导航优先,命令式导航用于流程跳转
Link/NavLink更适合 UI 层导航,因为它们保留了链接语义、可预期历史记录与激活状态。useNavigate更适合登录成功、提交后跳转、返回上一页、替换历史记录等流程控制。- 过度使用命令式导航,通常意味着把本应由链接表达的信息架构藏进了事件逻辑。
4. 状态表达模型:路径参数、查询参数与导航状态各有边界
- 路由状态分层:路径参数表达资源身份,查询参数表达筛选、排序、分页等可分享状态,location state 表达一次性导航上下文。
useParams适合读取/posts/:postId这类资源标识;useSearchParams适合维护搜索词、筛选条件、分页游标等 URL 状态。- 把筛选、排序、分页长期放在组件本地 state,会削弱链接分享、刷新恢复和浏览器历史行为。
5. 数据路由模型:路由成为数据读取、提交与错误处理边界
- 数据路由:
loader、action、errorElement让数据依赖、表单提交和错误边界跟随路由层级,而不是散落在组件内部的useEffect中。 - 组件式路由适合简单应用和入门理解;数据路由更适合中大型应用,因为它把页面进入前的数据依赖声明在路由层。
- 数据路由的价值不只是“少写请求代码”,而是把导航、加载、提交、错误恢复放进同一套页面生命周期模型里。
6. 架构边界:路由是加载、拆分与集成策略的入口
- 路由级渐进加载:路由天然是代码分割边界,适合按页面、次级面板、图表、评论区等粒度做懒加载与骨架屏。
- 路由级模块装配:当系统变大后,路由经常成为子系统挂载、预加载、权限控制和微前端集成的边界。
- 渐进式架构视角:React Router 的位置会延伸到 SPA、SSR、服务端重写、缓存策略和资源加载优先级之间的协同。
最小实践路径
- 先掌握
BrowserRouter、Routes、Route,理解路径如何映射页面组件。 - 再掌握
<Outlet />、嵌套路由、index路由,理解路由树如何映射布局树。 - 再掌握
Link、NavLink、useNavigate,区分 UI 导航与流程跳转。 - 再掌握
useParams、useSearchParams、location state,区分资源身份、可分享状态与一次性上下文。 - 再理解
loader、action、errorElement,把数据读取、提交和错误处理提升到路由层。 - 最后把路由放进懒加载、SSR、微前端和渐进式集成这些架构问题里看。
常见失误
BrowserRouter部署后刷新 404:服务端没有把未知路径回退到入口 HTML。- 父路由写了
children,但父组件里忘了放<Outlet />。 - 把筛选条件、分页、排序放在组件本地 state,导致链接无法分享、刷新无法恢复。
- 嵌套路由和 UI 结构不一致,导致路由表越来越难维护。
- 本来可以用
Link表达的信息架构,被过度写成useNavigate事件逻辑。 - 把数据请求全塞进组件
useEffect,导致页面进入后再瀑布式加载。
相关概念 / 下层卡片
- URL 作为应用状态:解释 React Router 为什么不是单纯跳转工具,而是让页面状态进入浏览器导航模型。
- 路由树与布局树同构:解释嵌套路由、布局路由和
<Outlet />的共同心智模型。 - 数据路由的问题解决:解释 loader / action / errorElement 试图修复的组件内请求、提交和错误处理分散问题。
- 路由状态表达边界:区分 params、search 与 location state 的适用场景。
相关入口
- 从历史模式理解路由基础:补充 BrowserRouter、HashRouter 与 History API 的实现原理。
- 从 Suspense 理解路由级懒加载:把页面切换和渐进渲染放到一起理解。
- 从微前端理解路由级集成:把路由看作模块装配与系统边界。
- 从渐进式集成理解 React Router 的架构位置:把 React Router 放进 SPA、SSR 与框架演进的连续谱里。
暂时结论
React Router 的核心学习路径是:先理解 URL 如何映射视图,再理解路由如何组织布局与加载,最后理解路由如何成为应用拆分和架构演进的入口。