news 2026/1/29 8:56:40

为什么状态一集中,所有 RN 性能优化都会失效

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
为什么状态一集中,所有 RN 性能优化都会失效

@[toc]

为什么这是一类“怎么优化都没用”的问题

RN 列表性能问题里,有一类非常让人崩溃的场景:

  • 你已经:

    • 用了React.memo
    • 用了useCallback
    • 控制了keyExtractor
    • 甚至拆了子组件
  • 但:

    • 点一个按钮,列表还是会卡
    • 滑动时偶发掉帧
    • 性能分析一看,renderItem 还是在狂跑

很多人会下意识得出一个结论:

FlatList 不行
RN 性能差
JS 线程太慢

但如果你回头看这些项目,80% 都有一个共同点

状态被集中管理了。

而且集中得“非常合理”。

什么叫“状态一集中”

先说清楚概念。

典型的“状态集中”长这样

function ListPage() { const [listState, setListState] = useState({ likedMap: {}, selectedMap: {}, expandedMap: {}, }) return ( <FlatList data={data} renderItem={({ item }) => ( <Item item={item} liked={listState.likedMap[item.id]} selected={listState.selectedMap[item.id]} /> )} /> ) }

业务角度看,这段代码没有任何问题:

  • 状态统一
  • 数据集中
  • 管理方便

但从渲染模型看,它已经埋下了一颗性能炸弹。

集中的不是“数据”,而是“影响范围”

真正的问题不在于你“把状态放一起了”,而在于:

任何一个状态变更,影响的最小单位是整个 ListPage

也就是说:

任意一个 item 的交互 → ListPage rerender → FlatList rerender → 所有 renderItem 重新执行

这条链路一旦成立,后面所有优化都会变成装饰品

为什么 memo / useCallback 在这里几乎没用

这是很多人最困惑的地方。

React.memo 只能挡 props 不变的 rerender

const Item = React.memo(({ liked }) => { ... })

看起来好像能挡住重渲染,对吧?

但问题在于:

  • liked是从listState解构出来的
  • 每次setListStatelistState都是一个新对象
  • renderItem 每次都会重新执行

结果是:

memo 挡住了 Item 的 render 函数,但挡不住 renderItem 本身

而 renderItem 恰恰是 FlatList 最重的一层。

useCallback 只能解决“函数引用”,解决不了“依赖变化”

const onLike = useCallback(() => { ... }, [listState])

只要你依赖的是集中状态对象

  • callback 每次都会重新创建
  • 下游组件依然会 rerender

你会发现一个很讽刺的现象:

状态越集中,useCallback 的 dependency 越大,越没意义

一次 state 更新,是如何引发“渲染雪崩”的

这一节我们用一个非常具体的 Demo,把链路拆清楚。

Demo:一个点赞引发的全列表重算

function ListPage() { const [likedMap, setLikedMap] = useState<Record<string, boolean>>({}) const toggleLike = (id: string) => { setLikedMap(prev => ({ ...prev, [id]: !prev[id], })) } return ( <FlatList data={data} renderItem={({ item }) => { console.log('render item', item.id) return ( <Item item={item} liked={likedMap[item.id]} onLike={() => toggleLike(item.id)} /> ) }} /> ) }

点任意一个 item,你会在控制台看到:

render item 1 render item 2 render item 3 ... render item 100

哪怕你只点了第 57 个。

真正发生的事情(不是你以为的)

你以为发生的是:

第 57 个 item 状态更新 → 第 57 个 item rerender

但实际上发生的是:

setLikedMap → ListPage rerender → FlatList rerender → renderItem 全量执行 → JS 线程瞬间被占满

这就是渲染扩散

为什么 FlatList 的优化参数救不了你

很多人会继续尝试:

  • initialNumToRender
  • windowSize
  • removeClippedSubviews

但这些参数解决的是:

“一次渲染多少 item”

而不是:

“为什么会触发渲染”

当渲染触发点在 ListPage 时:

  • FlatList 已经没有选择权了
  • 它只能老老实实重新算一遍 renderItem

真正有效的分界线:状态的“最小归属单位”

所有性能优化是否有效,只取决于一件事:

状态变化,能不能被限制在最小使用单元内

不可优化的模型

状态 → ListPage

任何变化,影响整个列表。

可优化的模型

状态 → Item

变化只影响自己。

把状态“拆散”,为什么性能突然就好了

我们直接对比两种写法。

集中式(不可扩展)

<Item liked={likedMap[item.id]} />

分散式(可扩展)

const Item = React.memo(({ item }) => { const [liked, setLiked] = useState(false) })

此时渲染链路变成:

Item setState → 当前 Item rerender
  • ListPage 不动
  • FlatList 不动
  • 其他 item 完全无感

你会发现一个非常明显的变化:

甚至不需要 memo,性能就已经很好了

Redux / Context 为什么会“让一切优化失效”

Redux 的问题不是慢,而是“订阅面太大”

useSelector(state => state.list)

任何 list 内字段变化:

  • selector 返回新引用
  • 所有订阅组件 rerender

在列表场景下,这几乎等价于:

每次交互 = 全列表 rerender

Context 是最容易被低估的性能杀手

<ListContext.Provider value={listState}>

Context 的规则非常简单粗暴:

value 变了,所有 consumer 必须更新

在列表里,这意味着:

Context 更新 = renderItem 全跑

为什么“状态集中”在 Web 里没这么致命

这是一个很关键的对比点。

在 Web 里:

  • DOM diff 有天然的兜底
  • 浏览器渲染线程很强
  • 局部 repaint 成本低

但在 RN 里:

  • JS → Shadow Tree → Native
  • 每一次 rerender 都是跨线程协作
  • JS 线程一旦被拖慢,滑动立刻掉帧

所以:

RN 对“状态扩散”是零容忍的

总结

RN 里所有性能优化是否生效,只取决于一件事:
状态变化能不能被限制在足够小的范围内

一旦状态被集中:

  • memo 会失效
  • useCallback 会失效
  • FlatList 参数会失效
  • 你只剩下“体感卡顿”
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/27 21:12:27

Google Colab + lora-scripts:免费GPU训练LoRA模型方法

Google Colab lora-scripts&#xff1a;免费GPU训练LoRA模型方法 在一张显卡动辄上万元、A100云实例每小时几十元的时代&#xff0c;普通人还有机会玩转AI模型微调吗&#xff1f;答案是肯定的——借助 Google Colab 的免费GPU 和开源工具 lora-scripts&#xff0c;你完全可以在…

作者头像 李华
网站建设 2026/1/28 5:25:24

Quarkus 2.0 + 物联网协同进化(5大真实场景落地案例全曝光)

第一章&#xff1a;Quarkus 2.0 物联网协同进化的时代背景随着边缘计算与5G网络的快速普及&#xff0c;物联网设备呈指数级增长&#xff0c;对低延迟、高吞吐和资源高效利用的后端框架提出了更高要求。Quarkus 2.0 的发布恰逢其时&#xff0c;它不仅强化了对 GraalVM 原生镜像的…

作者头像 李华
网站建设 2026/1/29 2:16:39

基于JavaSSM框架的线上管理系统

本文基于Java SSM框架设计并实现了一套线上管理系统&#xff0c;旨在提升企业信息管理效率&#xff0c;降低运营成本。系统采用Spring、Spring MVC和MyBatis三大核心框架构建&#xff0c;结合B/S架构与MySQL数据库&#xff0c;实现了客户信息、公告信息、员工信息等多模块的集中…

作者头像 李华
网站建设 2026/1/27 15:54:27

假期网络钓鱼攻击中DocuSign伪装与虚假贷款诈骗的融合机制分析

摘要近年来&#xff0c;网络钓鱼攻击在节假日期间呈现显著上升趋势&#xff0c;其攻击手法日趋复杂化与专业化。本文聚焦于2025年末至2026年初假期期间出现的一类新型复合型钓鱼攻击&#xff1a;攻击者通过伪造DocuSign电子签名通知邮件&#xff0c;诱导用户点击嵌入链接&#…

作者头像 李华
网站建设 2026/1/25 2:02:38

计算机毕设java校园二手物品交易平台 基于Java的校园二手交易系统开发与实现 Java技术驱动的校园二手物品交易管理平台设计

计算机毕设java校园二手物品交易平台1w6h09&#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。随着校园生活的日益丰富多彩&#xff0c;二手物品交易逐渐成为学生们处理闲置物品、节…

作者头像 李华
网站建设 2026/1/25 4:31:12

一点资讯个性化推送:根据用户画像发送lora-scripts资讯

一点资讯个性化推送&#xff1a;基于用户画像的 LoRA 定制化内容生成实践 在内容平台竞争日益激烈的今天&#xff0c;如何让推荐系统“懂我”不再只是点击率的游戏&#xff0c;而是真正理解用户的审美偏好与情感语境&#xff1f;传统通用大模型虽然能生成内容&#xff0c;但往往…

作者头像 李华