React性能优化总览
React 中渲染、列表、引用稳定性与缓存相关优化点的总览入口。
#tech / dev / frame
#resource / react
#type / synthesis
#status / growing
[!info] related notes
React性能优化总览
React 性能优化最容易走偏的地方,是还没定位瓶颈,就先到处加 memo、useMemo 和 useCallback。真正有效的优化,通常从理解渲染来源开始。
先建立正确前提
- 重渲染本身是 React 的正常工作方式
- 真正昂贵的,通常是重复计算、大列表、低效副作用或错误状态设计
- 优化应该服务真实瓶颈,而不是服务心理安慰
真正更重要的优化顺序
- 先保证数据流和依赖正确
- 再删除没必要的 state 和 Effect
- 再看状态边界、组件边界、列表结构
- 最后才考虑
memo、useMemo、useCallback
很多时候最有效的优化不是“缓存更多”,而是“少建模错误的状态”。
最常见的几个优化入口
状态边界
状态放得越合理,无意义联动越少。先看 react-component-design-principles。
渲染来源
先定位为什么会 rerender,再决定是否需要优化。见 React组件渲染与重渲染。
计算缓存
昂贵计算才值得考虑 react-use-memo。
引用稳定
只有当函数引用变化真的影响子组件或依赖项时,才需要 react-use-callback。
组件级跳过渲染
react-memo 适合稳定 props 的组件边界,但不是默认必加项。
列表渲染
长列表和错误 key 经常比普通 rerender 更容易出问题。见 react-list-rendering-and-key。
面试里怎么回答“React 性能优化”
这题最容易答偏成“背 API 清单”。更稳的答法应该先讲原则,再讲常见瓶颈,再讲工具。
一个更完整的回答可以是:
React 性能优化我一般先看是不是状态设计、渲染边界或副作用设计出了问题,而不是先到处加
memo。真正常见的瓶颈通常是状态放得太高导致联动重渲染、大列表渲染过重、引用不稳定让 memo 失效、或者 Effect 里做了不必要的工作。优化顺序上我会先定位重渲染来源,再优化状态边界和组件边界,最后才考虑React.memo、useMemo、useCallback这些缓存手段。
面试官真正想听什么
- 你是不是知道 rerender 本身不是原罪
- 你会不会先定位问题,而不是盲目加缓存
- 你是否理解状态边界、列表优化、引用稳定这些更本质的点
高频优化场景
1. 状态放得太高
- 父组件一个 state 变化,整片子树都跟着 rerender
- 这时更该考虑状态下沉、局部化,而不是先加
memo
2. 列表太大
- 大列表渲染和更新成本高
- 要看
key是否稳定 - 必要时考虑虚拟列表
3. 引用不稳定
- 父组件每次渲染都新建对象和函数
- 子组件用了
memo也可能照样 rerender
4. 昂贵计算
- 只有真的有重计算成本时,
useMemo才更有意义
5. Effect 做了太多事
- 错误的 Effect 往往比“没加 memo”更容易造成性能浪费
一个更工程化的排查顺序
- 先用 React DevTools Profiler 看谁在频繁 rerender
- 再判断是 state、props、context 还是列表结构导致
- 再决定是否需要缓存、拆分组件或重构状态位置
一条实用优化顺序
- 先确认慢在哪里
- 再看是不是状态设计或列表结构问题
- 最后才考虑
memo、useMemo、useCallback这类缓存手段
一个常见误区
很多人把优化理解成:
- 到处加
useMemo - 到处加
useCallback - 到处包
React.memo
但如果:
- 子组件本身不重
- 计算本身不贵
- 引用稳定并没有带来实际收益
这些缓存只会增加代码复杂度。
常见误区
- 把 React 优化理解成“尽量不 rerender”
- 还没定位瓶颈就全局加
memo - 以为
useCallback的价值是“少创建函数”,而不是“稳定引用” - 子组件本身不重、计算本身不贵时,仍然到处加
useMemo/useCallback/React.memo
最短记忆方式
React 优化不是“减少一切渲染”,而是减少真正昂贵且没有价值的工作。