news 2026/5/9 14:47:01

为什么状态一集中,所有 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/5/9 10:21:18

国产算力卡如寒武纪、昇腾能否运行lora-scripts?

国产算力卡如寒武纪、昇腾能否运行lora-scripts&#xff1f; 在生成式AI迅速渗透各行各业的今天&#xff0c;越来越多企业希望基于大模型进行垂直领域微调——比如为客服系统定制话术风格&#xff0c;或为设计团队训练专属IP形象画风。LoRA&#xff08;Low-Rank Adaptation&…

作者头像 李华
网站建设 2026/5/9 7:20:47

新手也能上手的LoRA训练神器:lora-scripts使用指南与实战案例

新手也能上手的LoRA训练神器&#xff1a;lora-scripts使用指南与实战案例 在AI生成内容&#xff08;AIGC&#xff09;逐渐渗透到创作、设计和企业服务的今天&#xff0c;一个现实问题摆在许多开发者面前&#xff1a;如何让强大的通用模型——比如Stable Diffusion或LLaMA——真…

作者头像 李华
网站建设 2026/5/6 9:11:13

negative_prompt优化建议:提升lora-scripts生成图质量

negative_prompt优化建议&#xff1a;提升lora-scripts生成图质量 在如今AIGC爆发式发展的环境下&#xff0c;越来越多创作者和开发者开始尝试使用LoRA&#xff08;Low-Rank Adaptation&#xff09;技术来定制专属的图像风格或角色模型。相比全参数微调&#xff0c;LoRA以极低…

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

C++26任务调度革命(std::execution核心特性全曝光)

第一章&#xff1a;C26任务调度革命&#xff1a;std::execution的全景展望C26即将迎来一项深远影响并发编程范式的变革——std::execution 的全面引入。这一机制旨在统一并简化异步任务的调度与执行策略&#xff0c;使开发者能够以声明式方式指定任务应在何种上下文中运行&…

作者头像 李华
网站建设 2026/5/3 16:32:22

揭秘C++26 std::execution调度机制:如何实现高效并行任务管理

第一章&#xff1a;C26 std::execution 任务调度概述C26 引入了 std::execution 命名空间&#xff0c;旨在为并发和并行任务提供统一、高效且可组合的调度机制。该特性扩展了早期标准中对执行策略的初步支持&#xff0c;将任务调度从简单的并行执行升级为细粒度控制的任务图管理…

作者头像 李华
网站建设 2026/5/4 13:27:01

Yandex俄罗斯市场推广:拓展lora-scripts使用范围

Yandex俄罗斯市场推广&#xff1a;拓展lora-scripts使用范围 在生成式人工智能&#xff08;AIGC&#xff09;迅速渗透各行各业的今天&#xff0c;企业不再满足于“通用模型简单调用”的初级应用模式。越来越多的业务场景要求AI具备鲜明的本地化特征——无论是东正教教堂穹顶上的…

作者头像 李华