从 Navigation State 反推架构腐化

@[toc

------为什么导航状态,往往是 RN 项目里最早"变味"的地方

如果你做过中大型 RN 项目,大概率会遇到一种情况:

项目明明还能跑,但你已经不太敢动导航相关的代码了。

加一个页面要想半天,

改一个返回逻辑要全局搜 goBack

线上 bug 说"返回错页",你只能本地反复点。

这不是你不熟 React Navigation,而是项目的"页面模型"已经开始腐化了。

而最早暴露腐化信号的地方,往往不是 UI、不是业务逻辑,而是------
Navigation State。

这篇文章,我们就反过来:

不从"怎么写导航",而是从 Navigation State 的异常形态,一步步反推出 RN 项目正在发生的架构问题。

一、Navigation State 是什么,它为什么这么"诚实"

先明确一个认知:

Navigation State 是当前 App 页面世界的完整快照。

在 React Navigation 中,一个典型的 state 长这样:

js 复制代码
{
  type: 'stack',
  key: 'root-stack',
  index: 1,
  routes: [
    { name: 'Home', key: 'Home-xxx' },
    {
      name: 'Profile',
      key: 'Profile-yyy',
      state: {
        type: 'tab',
        index: 0,
        routes: [
          { name: 'Info' },
          { name: 'Settings' }
        ]
      }
    }
  ]
}

它包含了:

  • 当前有哪些页面
  • 页面嵌套关系
  • 当前焦点在哪
  • 哪些 Navigator 还"活着"

它不关心你怎么组织代码,只忠实记录"现在页面真实长什么样"。

也正因为这样:

Navigation State 是不会撒谎的。

二、什么叫"架构腐化",在导航层长什么样

很多人一听"架构腐化",会觉得很抽象。

但在 RN 项目里,它在导航层的表现非常具体。

下面这些现象,你一定见过。

1. State 越看越长,看不懂层级

刚开始项目时:

text 复制代码
RootStack
 ├─ Login
 └─ MainTabs

半年后变成:

text 复制代码
RootStack
 ├─ Login
 ├─ MainTabs
 │   ├─ HomeStack
 │   │   ├─ Home
 │   │   ├─ Detail
 │   │   └─ DetailModal
 │   ├─ ProfileStack
 │   │   ├─ Profile
 │   │   ├─ Edit
 │   │   └─ EditConfirm
 │   └─ WebStack
 │       ├─ Web
 │       └─ WebModal
 └─ TempStack
     ├─ Guide
     └─ Promo

你会发现:

  • Navigator 一层套一层
  • 有些 Stack 是"临时加的"
  • 有些页面其实业务已经下线,但导航还在

这不是业务复杂,而是页面边界已经失控。

2. 同一个页面名,在 State 里出现多次

这是一个非常危险的信号。

你在 state 里看到:

js 复制代码
routes: [
  { name: 'Detail', key: 'Detail-1' },
  { name: 'Detail', key: 'Detail-2' }
]

这通常意味着:

  • 页面被当成"流程节点"在用
  • 开发者不知道该 push 还是 replace
  • 没有页面唯一职责的概念

结果就是:

  • 返回逻辑不可预测
  • 页面栈越走越深
  • Android Back 行为开始失控

比如:

  • 登录后,AuthStack 还留在 state 里
  • 新手引导结束,GuideStack 只是被 navigate 覆盖
  • 弹窗用 Stack 实现,但永远不被清理

这些 Navigator 不是"不可见",而是"还活着"。

它们会在:

  • 返回时突然被激活
  • 状态恢复时重新出现
  • 热更新后引发幽灵页面

三、Navigation State 为什么会最先暴露问题

这是 RN 项目一个很有意思的现象。

1. 业务可以靠条件判断"苟住"

业务代码里你可以写:

js 复制代码
if (!data) return null

或者:

js 复制代码
if (userType === 'A') { ... }

很多混乱,其实被 if else 掩盖了。

2. 但导航是"结构性"的

导航不是条件渲染,它是结构决策

  • 页面是不是还在栈里
  • Navigator 是否被卸载
  • 返回链路是否单一

这些问题,一旦设计错了,就会长期存在于 State 里

3. 所以 State 就像"X 光片"

UI 看着正常,但 State 已经骨折了。

下面是一个可以直接落地的调试/评估流程

在根导航容器:

js 复制代码
const navigationRef = createNavigationContainerRef()

<NavigationContainer
  ref={navigationRef}
  onStateChange={(state) => {
    console.log(JSON.stringify(state, null, 2))
  }}
>
  {children}
</NavigationContainer>

这是所有分析的起点。

第二步:问三个核心问题

问题一:这个页面"为什么还在"

如果你在 state 里看到一个页面,问自己:

如果我现在按返回,它真的有业务意义吗?

如果答案是否定的,那就是:

  • 页面职责不清
  • 退出逻辑缺失
  • 生命周期设计失败

很多 Stack 的诞生过程是:

"这里逻辑有点乱,包一层 Stack 吧"

但后续没人再问:

  • 它是不是还必要
  • 是否可以合并
  • 是否应该在流程结束后被 reset
问题三:返回链路是不是唯一的

理想状态:

任意页面,返回路径只有一条。

如果你发现:

  • A 页面可能回 B
  • 也可能回 C
  • 取决于你是从哪跳过来的

那基本可以断定:

这是流程型页面被当成普通页面在用。

场景:订单流程越改越乱

假设你有这样一个流程:

复制代码
List → Detail → Pay → Result

一开始你写的是:

js 复制代码
navigation.navigate('Detail')
navigation.navigate('Pay')
navigation.navigate('Result')

State 会变成:

js 复制代码
[List, Detail, Pay, Result]

后来需求来了:

  • 支付失败要回 Pay
  • 从订单列表也能直接进 Result

于是你开始混用:

js 复制代码
navigate
push
replace
goBack

半年后 State 可能是:

js 复制代码
[List, Detail, Pay, Detail, Result]

此时你已经很难只靠代码理解返回逻辑了。

改造思路:流程页面 = 状态机,而不是栈

正确做法是:

  • 流程结束,直接 reset
  • 流程中禁止"自由返回"
js 复制代码
navigation.reset({
  index: 0,
  routes: [{ name: 'Result' }]
})

这样 State 会被主动修剪

六、一个成熟 RN 项目,Navigation State 应该长什么样

不是越简单越好,而是越可预测越好

它通常具备几个特征:

  1. Root 层很薄

    • Auth / Main / Modal
  2. 流程型页面生命周期清晰

    • 开始创建
    • 结束销毁
  3. 返回路径单一

    • 没有"看运气返回"
  4. 临时 Navigator 会被 reset

    • 不留下历史包袱

七、结语:导航不是工具问题,而是建模能力问题

很多 RN 项目最后变成"导航地狱",并不是因为:

  • React Navigation 不好
  • API 太复杂

而是因为:

开发者从来没有认真对待过"页面模型"这件事。

Navigation State 之所以重要,是因为它:

  • 不参与业务争论
  • 不关心你写得漂不漂亮
  • 只如实反映架构质量

如果你愿意花时间读懂它、修剪它、约束它

你会发现:

很多 RN 项目"不可维护"的问题,其实在导航层早就写在那了。

相关推荐
Zoey的笔记本几秒前
敏捷与稳定并行:Scrum看板+BPM工具选型指南
大数据·前端·数据库·python·低代码
文心快码BaiduComate2 分钟前
0代码手写!体验百度Comate的“魔法”:我造了个会理解情绪的中介层
前端·程序员·前端框架
38242782710 分钟前
表单提交验证:onsubmit与return详解
前端·javascript·html
前端小蜗11 分钟前
普通前端程序员的 2025:没什么大胜利,但也没被生活击倒
前端
科技小E24 分钟前
EasyGBS算法算力融合架构:标准平安乡村智能视频监控建设方案设计
架构·音视频
bug总结34 分钟前
身份证号脱敏的正确实现
前端·javascript·vue.js
林太白1 小时前
Vite8 Beta来了,Rolldown携手Oxc
前端·javascript·后端
xkxnq1 小时前
第二阶段:Vue 组件化开发(第 19天)
前端·javascript·vue.js
檐下翻书1732 小时前
PC端免费跨职能流程图模板大全 中文
大数据·人工智能·架构·流程图·论文笔记
技术净胜2 小时前
Python 操作 Cookie 完全指南,爬虫与 Web 开发实战
前端·爬虫·python