React 性能优化
触发 React 组件的 Render 过程目前有三种方式,分别为 forceUpdate、State 更新、父组件 Render 触发子组件 Render 过程
优化技巧
- 跳过不必要的组件更新。这类优化是在组件状态发生变更后,通过减少不必要的组件更新来实现
- 提交阶段优化。这类优化的目的是减少提交阶段耗时
- 前端通用优化。这类优化在所有前端框架中都存在
跳过不必要的组件更新
PureComponent、React.memo
在 React 工作流中,如果只有父组件发生状态更新,即使父组件传给子组件的所有 Props 都没有修改,也会引起子组件的 Render 过程。从 React 的声明式设计理念来看,如果子组件的 Props 和 State 都没有改变,那么其生成的 DOM 结构和副作用也不应该发生改变。当子组件符合声明式设计理念时,就可以忽略子组件本次的 Render 过程。PureComponent 和 React.memo 就是应对这种场景的,PureComponent 是对类组件的 Props 和 State 进行浅比较,React.memo 是对函数组件的 Props 进行浅比较
shouldComponentUpdate
仅在「子组件使用的属性」发生改变时才返回 true
,便能避免子组件重新 Render。
useMemo、useCallback 实现稳定的 Props 值
Hooks 按需更新
性能优化的话要知道一点
减少没必要的组件的渲染
把 React 比喻成一个大家族,假设妈妈在做饭,做好后,通知一声,大家来
如果做好一道,就喊一次:我做了 XX 菜,还有几道菜,其他人喊好的。其他人在这其中就是没必要说的,按照 React 的说法,就是没必要渲染
废话不多说,亮代码:
import React from 'react';
const Son = () => {
console.log('son render');
return <div>我是儿子,在玩电脑</div>;
};
const Daughter = () => {
console.log('daughter render');
return <div>我是女儿,在刷小红书</div>;
};
const Mother = () => {
console.log('mother render');
return <div>我是妈妈,在炒菜</div>;
};
const Father = () => {
console.log('father render');
return <div>我是爸爸,在看NBA</div>;
};
const Uncle = () => {
console.log('uncle render');
return <div>我是叔叔,在研究虚拟货币</div>;
};
const Aunt = () => {
console.log('aunt render');
return <div>我是婶婶,在带货直播</div>;
};
const Grandfather = () => {
console.log('grandfather render');
return <div>我是爷爷,在发呆</div>;
};
const GrandMother = () => {
console.log('grandmother render');
return <div>我是奶奶,在打电话</div>;
};
const Family = () => {
return (
<>
<GrandMother />
</>
);
};
const App = () => {
return <Family />;
};
memo 就是减少组件的没必要的渲染,做浅对比
函数式性能优化
主要是 hooks
useMemo、useCallback、memo
类组件性能优化
shouldComponentUpdate、pureComponent
shouldComponentUpdate 与 memo 的区别
案例分析
1000 条数据的解决方案——跳转
「性能优化」的核心应当是「不订阅视图无关的数据,以避免重复渲染」
而不是「订阅了视图无关的数据,用 useCallback/useMemo 来缓解性能问题」
React 渲染性能优化有三个方向:
- 减少计算的量
- 即减少渲染的节点或者降低组件渲染的复杂度
- 利用缓存
- 如何避免重新渲染,利用函数式编程的 memo 方式来避免组件重新渲染
- 精确重新计算的范围
- 绑定组件和状态关系,精确判断更新的”时机“和”范围“,只重新渲染”脏“的组件,或者说降低渲染范围
memo
与 shouldComponentUpdate 的效果一样
const areEqual = (prevProps, nextProps) => {
// 返回结果和shouldComponentUpdate正好相反
// 访问不了state
};
React.memo(Foo, areEqual);
参考资料
- 浅谈 React 性能优化的方向
- 记忆化技术 memoize-one
- 「框架篇」React 中 的 9 种优化技术
- React 高效渲染策略
- 如何全方位优化你的超大型 React 应用 【原创精读】
- 干货:深入了解 React 渲染原理及性能优化
- 可能你的 react 函数组件从来没有优化过
- React 函数式组件性能优化指南
- 打造高性能的 React 应用的几种方式总结
- 「react 进阶」react 开发者的不得不知道的八条优化建议
- 这可能是全网最全的 react 性能优化知识锦集
- 从源码中来,到业务中去,React 性能优化终极指南
- React Performance Optimization Tips
- 新版 react 中,usecallback 和 usememo 是不是值得大量使用?
- React 性能优化 | 包括原理、技巧、Demo、工具使用