众所周知,在React中,当父组件重新渲染时,正常情况下会对所有子孙级组件进行重新渲染。然而有时候子组件其实并未使用父组件的任何参数,这时候对子孙级的组件进行重新渲染是不必要的。这时候我们就需要使用React.PureComponent与React.memo进行性能优化了。
import Children from './Children';
import { useState } from 'react';
// 父组件
const Parent = () => {
const [count, setCount] = useState<number>(0);
return (
<div style={
{ padding: 40 }}>
<div>count: {count}</div>
<button onClick={() => setCount((c) => ++c)}>count + 1</button>
<Children />
</div>
);
};
export default Parent;
import React from 'react';
// 子组件
export default class Children extends React.Component {
render() {
console.log('Children 被重新绘制');
return <div>Children component</div>;
}
}
点击10次后的结果 :
一、React.PureComponent
React.PureComponent中内置shouldComponentUpdate方法,以浅层对比 prop 和 state 的方式来实现了该函数。在 props 和 state 较为简单时,可以使用React.PureComponent来防止组件不必要的更新。
但是由于是浅层对比,如果 props 和 state 对象中包含复杂的数据结构,则有可能因为无法检查深层的差别,产生错误的比对结果,这时候推荐任然使用React.Component的方式通过手动写入shouldComponentUpdate来进行深层比较。
比如,此时能防止Children 被重新绘制:
import React from 'react';
// 子组件
export default class Children extends React.PureComponent {
render() {
console.log('Children 被重新绘制');
return <div>Children component</div>;
}
}
点击10次后的结果 :
二、React.memo
React.memo为高阶组件,与React.PureComponent相似,但是其仅检查 props 变更。如果函数组件被 React.memo 包裹,但是组件内拥有 useState、useReducer 或 useContext 的 Hook,当 state 或 context 发生变化时,组件仍会重新渲染。
import React from 'react';
// 子组件
class Children extends React.Component {
render() {
console.log('Children 被重新绘制');
return <div>Children component</div>;
}
}
export default React.memo(Children);
当然,其实React.memo是为了更好的解决函数类组件难以处理性能优化问题的痛点的:
import React from 'react';
// 子组件
const Children = () => {
console.log('Children 被重新绘制');
return <div>Children component</div>;
};
export default React.memo(Children);
点击10次后的结果 :
另外,React.memo支持通过第二个参数传入来控制对比过程,如果需要对props进行深层对比,则建议使用第二个参数:
import React from 'react';
// 子组件
const Children = () => {
console.log('Children 被重新绘制');
return <div>Children component</div>;
};
export default React.memo(Children, (prevProps, nextProps) => {
/*
如果把 nextProps 传入 render 方法的返回结果与将 prevProps 传入 render 方法的返回结果一致,
则返回 true,
否则返回 false。
*/
return true;
});
注意:
与 class 组件中 shouldComponentUpdate() 方法不同的是,如果 props 相等,
areEqual
会返回true
;如果 props 不相等,则返回false
。这与shouldComponentUpdate
方法的返回值相反。
结尾:在某些场景下,我们建议使用React.PureComponent 或者 React.memo()来进行性能优化。但并不是所有的组件都要引入的,因为自身浅对比这个过程也会有少许性能消耗,你需要根据项目的实际情况来决定是否使用。
参考: