用一张“状态扩散图”,定位 RN 列表性能风险



子玥酱 (掘金 / 知乎 / CSDN / 简书 同名)

大家好,我是 子玥酱,一名长期深耕在一线的前端程序媛 👩‍💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。

我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括 前端工程化、小程序、React / RN、Flutter、跨端方案,

在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。

技术方向: 前端 / 跨端 / 小程序 / 移动端工程化 内容平台: 掘金、知乎、CSDN、简书 创作特点: 实战导向、源码拆解、少空谈多落地 **文章状态:**长期稳定更新,大量原创输出

我的内容主要围绕 前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读 展开。文章不会停留在"API 怎么用",而是更关注为什么这么设计、在什么场景下容易踩坑、真实项目中如何取舍,希望能帮你在实际工作中少走弯路。

子玥酱 · 前端成长记录官 ✨

👋 如果你正在做前端,或准备长期走前端这条路

📚 关注我,第一时间获取前端行业趋势与实践总结

🎁 可领取 11 类前端进阶学习资源 (工程化 / 框架 / 跨端 / 面试 / 架构)

💡 一起把技术学"明白",也用"到位"

持续写作,持续进阶。

愿我们都能在代码和生活里,走得更稳一点 🌱

文章目录

为什么你需要一张"状态扩散图"

在 RN 项目里,很多性能问题其实都有一个共同特点:

  • 不好复现
  • 不好量化
  • 不好定位

尤其是列表场景,经常出现这种情况:

数据不多

手机性能也不差

偶尔就是掉一帧

这类问题,如果你只靠:

  • "加 memo"
  • "改 FlatList 参数"
  • "试试看能不能顺一点"

基本等于蒙。

真正有效的方式,是在写代码之前就判断:

这个状态更新,会扩散到哪里?

而"状态扩散图",就是把这个问题一次性说明白的工具。

什么是"状态扩散"

先别急着画图,我们先把概念说清楚。

状态扩散不是"状态变多"

很多人以为:

状态多 = 性能差

这是不对的。

真正危险的是:

一个状态更新,会影响多少组件参与 rerender

这就是"扩散半径"。

一个极简定义

你可以把它记成一句话:

状态扩散 = 一次 setState,引发的组件重渲染路径

路径越长、覆盖面越大,性能风险越高。

最危险的"全列表扩散型"

我们先从最常见、也是最危险的一种状态模型开始。

代码结构

tsx 复制代码
function ListPage() {
  const [likedMap, setLikedMap] = useState({})

  return (
    <FlatList
      data={data}
      renderItem={({ item }) => (
        <Item liked={likedMap[item.id]} />
      )}
    />
  )
}

状态扩散图

复制代码
setLikedMap
   ↓
ListPage rerender
   ↓
FlatList rerender
   ↓
renderItem(全部)
   ↓
Item(全部)

风险评估

  • 扩散起点:Item 级交互
  • 扩散终点:整个列表
  • 扩散层级:4 层
  • 扩散数量:N(列表长度)

结论只有一句话:

这是一个"必卡型"结构,只是早晚问题。

Context 驱动的"隐形全量扩散"

这一种,比第一种更容易被忽略。

看起来很"架构化"的写法

tsx 复制代码
<ListContext.Provider value={listState}>
  <FlatList ... />
</ListContext.Provider>
tsx 复制代码
function Item() {
  const { likedMap } = useContext(ListContext)
}

状态扩散图

复制代码
Context value 更新
   ↓
所有 Consumer rerender
   ↓
所有 Item rerender

为什么它特别危险

因为:

  • Context 更新没有 selector
  • 不管你用不用那一项数据
  • 只要 value 引用变了,必 rerender

你会发现一个很残酷的事实:

Context 在列表里,几乎等价于"广播状态"

Redux 的"选择器扩散型"

Redux 经常被误伤,说它"慢",其实问题不在 Redux 本身。

典型写法

tsx 复制代码
const likedMap = useSelector(state => state.likedMap)

状态扩散图

复制代码
dispatch
   ↓
store 更新
   ↓
selector 返回新引用
   ↓
订阅组件 rerender

如果订阅发生在:

  • ListPage
  • renderItem 内
  • Item 内但 selector 粒度过大

那结果就是:

Redux 版本的"全列表扩散"

可控的"局部扩散型"

现在来看一张健康的状态扩散图

Item 自持状态

tsx 复制代码
const Item = React.memo(({ item }) => {
  const [liked, setLiked] = useState(false)
})

状态扩散图

复制代码
Item setState
   ↓
当前 Item rerender

风险评估

  • 扩散起点:Item
  • 扩散终点:Item
  • 扩散层级:1
  • 扩散数量:1

这是 RN 列表里最理想的状态模型。

Zustand / Jotai 的"精准订阅型"

这类状态管理工具,在 RN 列表里表现好的原因,本质也在这里。

精准订阅示例

tsx 复制代码
const liked = useStore(state => state.liked[item.id])

状态扩散图

复制代码
store 更新
   ↓
命中 selector
   ↓
当前 Item rerender

关键点不在"快",在"窄"

  • 不是 store 更新小
  • 是 rerender 命中范围小

把图连起来:你现在在哪一层?

你可以把 RN 列表里的状态模型,直接分成这几档:

复制代码
Level 1:Item 局部状态
Level 2:Item 精准订阅 store
Level 3:ListPage 局部状态
Level 4:Context 广播状态
Level 5:Redux 大对象订阅

越往下:

  • 状态扩散半径越大
  • 性能风险指数级上升

真实项目中的一个判断方法

以后你看任何一个 RN 列表,只问自己 3 个问题:

  1. 这个状态更新,最先 rerender 的组件是谁?
  2. rerender 会不会回到 FlatList 这一层?
  3. renderItem 会不会因此全量执行?

只要有一个答案是"会",你就已经可以预判:

这个列表,一定会在未来某个需求下卡。

总结

RN 列表性能问题,真正的分水岭不是:

  • 用不用 FlatList
  • 用不用 memo
  • 用不用高端手机

而是:

你有没有在脑子里,提前画过一张"状态扩散图"

一旦你开始用这种方式看代码:

  • 性能问题会提前暴露
  • 架构问题会提前规避
  • 优化不再是救火,而是设计的一部分
相关推荐
LYFlied1 小时前
从 Vue 到 React,再到 React Native:资深前端开发者的平滑过渡指南
vue.js·react native·react.js
王码码20353 小时前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
坚果派·白晓明4 小时前
在鸿蒙设备上快速验证由lycium工具快速交叉编译的C/C++三方库
c语言·c++·harmonyos·鸿蒙·编程语言·openharmony·三方库
lbb 小魔仙4 小时前
【HarmonyOS实战】OpenHarmony + RN:自定义 useFormik 表单处理
react native·harmonyos
果粒蹬i4 小时前
【HarmonyOS】DAY7:鸿蒙跨平台 Tab 开发问题与列表操作难点深度复盘
华为·harmonyos
王码码20355 小时前
Flutter for OpenHarmony 实战之基础组件:第二十七篇 BottomSheet — 动态底部弹窗与底部栏菜单
android·flutter·harmonyos
AAA阿giao5 小时前
从零拆解一个 React + TypeScript 的 TodoList:模块化、数据流与工程实践
前端·react.js·ui·typescript·前端框架
ITUnicorn5 小时前
【HarmonyOS6】ArkTS 自定义组件封装实战:动画水杯组件
华为·harmonyos·arkts·鸿蒙·harmonyos6
全栈探索者6 小时前
@Component + struct = 你的新函数组件——React 开发者的鸿蒙入门指南(第 2 期)
react·harmonyos·arkts·前端开发·deveco studio·鸿蒙next·函数组件
廖松洋(Alina)6 小时前
【收尾以及复盘】flutter开发鸿蒙APP之成就徽章页面
flutter·华为·开源·harmonyos·鸿蒙