鄂州市网站建设_网站建设公司_动画效果_seo优化
2025/12/22 10:40:17 网站建设 项目流程

网罗开发(小红书、快手、视频号同名)

大家好,我是展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。

图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG

我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。

展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索“展菲”,即可纵览我在各大平台的知识足迹。
📣 公众号“Swift社区”,每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友“fzhanfei”,与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!


文章目录

    • 摘要
    • 为什么很多 RN 开发者“学过 Navigation,但还是用错了”
    • 先建立一个总览:三层生命周期同时存在
      • 第一层:React 组件生命周期
      • 第二层:Navigation 页面生命周期
      • 第三层:业务生命周期(用户视角)
    • 核心结论先给出
    • 从一个最常见的页面跳转说起
      • 实际发生了什么(默认配置)
    • 时间轴拆解:一次完整的页面往返
      • 第一次进入 Home
      • 从 Home 跳转到 Detail
      • 从 Detail 返回 Home
    • 用一张“心智模型表”记住它
    • 为什么 useEffect 在 Navigation 中经常“失灵”
    • 正确的心智转变:页面 = 有状态的长生命周期对象
    • 什么时候该用 useEffect,什么时候该用 useFocusEffect
      • 适合 useEffect 的场景
      • 必须用 useFocusEffect 的场景
    • 一个完整的可运行示例:对比两种写法
      • 错误示例:useEffect 管理页面请求
      • 正确示例:useFocusEffect 管理页面请求
    • unmountOnBlur 是“银弹”吗?
      • 它能解决什么?
      • 它带来的代价
    • 一个判断标准:问自己三个问题
    • 总结

摘要

在 React Navigation 里,生命周期问题几乎是所有复杂 Bug 的源头

很多看起来“很诡异”的现象,本质上都能归结为一句话:

你以为页面已经销毁了,但它其实还活着
你以为 useEffect 会重新跑,但它其实根本没机会

这篇文章不打算从 API 一个个列,而是从心智模型出发,帮你真正建立三件事的统一认知:

  • 组件生命周期(React)
  • 页面生命周期(Navigation)
  • 业务生命周期(用户视角)

当这三层对齐之后,你会发现:

  • 页面切换不再“玄学”
  • 副作用管理变得非常清晰
  • 很多历史遗留 Bug 一下子就能解释通了

为什么很多 RN 开发者“学过 Navigation,但还是用错了”

先说一个非常真实的现象。

你可能:

  • 用过useEffect
  • 用过useFocusEffect
  • 也知道有focusblur

但当遇到下面这些问题时,还是会懵:

  • 为什么返回页面后数据没刷新?
  • 为什么某个请求跑了两次?
  • 为什么定时器越跑越多?
  • 为什么 setState 报错组件已卸载,但我明明还能看到页面?

原因只有一个:
你脑子里只有“组件生命周期”,没有“页面生命周期模型”。

先建立一个总览:三层生命周期同时存在

在 RN + React Navigation 中,你必须同时理解三套生命周期。

第一层:React 组件生命周期

这是大家最熟的:

  • mount
  • update
  • unmount
  • useEffect / cleanup

它只关心一件事:组件在不在内存里。

第二层:Navigation 页面生命周期

这是最容易被忽略的:

  • focus
  • blur
  • transition
  • stack 中的存在状态

它关心的是:页面是否处于“当前活跃状态”。

第三层:业务生命周期(用户视角)

这是最容易被写错的:

  • 用户是否正在看这个页面
  • 用户是否关心当前副作用
  • 当前逻辑是否“还有意义”

绝大多数副作用,其实属于这一层。

核心结论先给出

在进入细节之前,先给你三条“底层规则”,后面所有内容都会围绕它展开。

  1. 页面 blur ≠ 组件 unmount
  2. useEffect 默认只和 mount / unmount 有关
  3. 绝大多数业务副作用,应该绑定 focus / blur,而不是 mount

如果你把这三条真正吃透,80% 的 Navigation Bug 都会消失。

从一个最常见的页面跳转说起

我们从最典型的 Stack Navigation 开始。

Home → Detail → Profile

实际发生了什么(默认配置)

当你从 Home 跳到 Detail:

  • Home:blur
  • Detail:mount + focus
  • Home:仍然 mounted

再从 Detail 跳到 Profile:

  • Detail:blur
  • Profile:mount + focus
  • Home、Detail:全部还在内存里

这一步,是很多人理解错误的起点。

时间轴拆解:一次完整的页面往返

我们用 Home → Detail → Home 举例。

第一次进入 Home

Home mount Home focus
  • useEffect(() => {}, [])执行
  • useFocusEffect执行

从 Home 跳转到 Detail

Home blur Detail mount Detail focus

注意这一步:

  • Home没有 unmount
  • Home 的useEffect cleanup不会执行

从 Detail 返回 Home

Detail blur Home focus

这里是高频踩坑点:

  • Home不会重新 mount
  • useEffect(() => {}, [])不会再跑
  • 只有 focus 相关逻辑会触发

用一张“心智模型表”记住它

行为useEffect([])useFocusEffect组件是否存在
首次进入页面执行执行
跳转到其他页面不触发cleanup
返回页面不执行再次执行
页面被真正销毁cleanupcleanup

这张表,建议你直接刻进脑子里。

为什么 useEffect 在 Navigation 中经常“失灵”

很多人会写这样的代码:

useEffect(() => { fetchData(); }, []);

然后发现:

  • 页面第一次进来 OK
  • 返回页面后数据不刷新
  • 只能靠手动刷新兜底

问题不是 useEffect 有 bug,而是你把“页面激活”当成了“组件创建”。

在 Navigation 世界里:

页面重新可见 ≠ 组件重新创建

正确的心智转变:页面 = 有状态的长生命周期对象

你应该把一个 Screen 理解为:

一个长期存在的对象,在不同时间段被 focus / blur

而不是:

每次进入就 new 一个,用完就销毁

一旦你接受了这个模型,很多设计会自然发生变化。

什么时候该用 useEffect,什么时候该用 useFocusEffect

这是最实用的问题,没有之一。

适合 useEffect 的场景

这些逻辑只和组件存在有关

  • 初始化静态配置
  • 注册全局工具(一次即可)
  • 只需要执行一次的逻辑
useEffect(() => { initAnalytics(); }, []);

必须用 useFocusEffect 的场景

这些逻辑和页面是否可见强相关

  • 页面级数据请求
  • 轮询 / 定时器
  • WebSocket 订阅
  • 页面埋点曝光
  • 动画启动 / 停止
useFocusEffect( useCallback(() => { startPolling(); return stopPolling; }, []) );

一个完整的可运行示例:对比两种写法

错误示例:useEffect 管理页面请求

useEffect(() => { console.log('fetch data'); fetchData(); }, []);

表现:

  • 只在第一次进入时请求
  • 返回页面数据不更新

正确示例:useFocusEffect 管理页面请求

useFocusEffect( useCallback(() => { console.log('fetch data on focus'); fetchData(); }, []) );

表现:

  • 每次页面可见都会触发
  • 行为符合用户直觉

unmountOnBlur 是“银弹”吗?

很多人会问:
我直接把页面 blur 时 unmount 不就完了?

options={{ unmountOnBlur: true }}

它能解决什么?

  • 副作用自动清理
  • useEffect 行为更“像直觉”

它带来的代价

  • 页面状态完全丢失
  • 重进页面性能开销变大
  • 动画 / 滚动位置无法保留

结论是:

它是工具,不是默认答案

大多数情况下,你需要的是:

  • 正确管理 focus 生命周期
  • 而不是强行销毁页面

一个判断标准:问自己三个问题

每次写副作用前,问自己:

  1. 页面不可见时,这个逻辑还有意义吗?
  2. 用户切走页面后,我是否还关心这个结果?
  3. 返回页面时,是否应该“重新激活”它?

如果答案偏向“是 / 否”,你就知道该选哪种生命周期了。

总结

React Navigation 的生命周期并不复杂,复杂的是我们用错了抽象层级

你真正需要记住的只有一句话:

组件生命周期决定“在不在”,页面生命周期决定“该不该跑”。

当你把:

  • useEffect → 组件存在
  • useFocusEffect → 页面可见

这条边界画清楚之后:

  • 页面逻辑会变得非常稳定
  • Bug 数量会明显下降
  • 项目越大,收益越明显

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询