React子组件性能优化
2021 react在 React 中,父组件的重新 render 会引发子组件的重新 render。
子组件的重新渲染
类组件
import React from 'react';
class Child extends React.Component {
render() {
console.log('child render');
return <>This is Child Component</>;
}
}
export default class App extends React.Component {
state = {
count: 0,
};
handleClick = () => {
this.setState({
count: this.state.count + 1,
});
};
render() {
return (
<>
<div>
<button onClick={this.handleClick}>click me</button>
count: {this.state.count}
</div>
<Child />
</>
);
}
}
函数组件
import React, { useState } from 'react';
function Child() {
console.log('child render');
return <>This is Child Component</>;
}
export default function App() {
const [count, setCount] = useState(0);
return (
<>
<div>
<button onClick={() => setCount(count + 1)}>click me</button>
count: {count}
</div>
<Child />
</>
);
}
在上面的类组件和函数组件中,我们点击按钮 click,会刷新 count 值,导致父组件刷新,而子组件没有做任何状态的变化,但是也一并重新渲染。
为了避免不必要的渲染更新,提高渲染效率,有三个主要的方式:
- shouldComponentUpdate
- PureComponent
- React.memo
类组件
React.PureComponent
class Child extends React.PureComponent {
render() {
console.log('child render');
return <>This is Child Component</>;
}
}
React.PureComponent 会以浅层对比 props 和 state 的方式实现函数。如果赋值了组件相同的 props 和 state,PureComponent 则可以提高性能,不进行重复渲染。
PureComponent 中的 shouldComponentUpdate() 仅作对象的浅层比较。如果对象中包含复杂的数据结构,则有可能因为无法检查深层的差别,产生错误的对比结果。
且 PureComponent 中将跳过所有子组件树的 props 更新,因此确保所有子组件也是 PureComponent。
shouldComponentUpdate
class Child extends React.Component {
shouldComponentUpdate() {
return false;
}
render() {
console.log('child render');
return <>This is Child Component</>;
}
}
通过使用 shouldComponentUpdate(nextProps, nextState) 进行对比,通过最终返回的 boolean 值决定是否重新渲染。
此方法仅作为性能优化的方式而存在,可以将 this.props 与 nextProps 以及 this.state 与 nextState 进行比较,并返回 false 跳过更新。返回 false 并不会阻止在 state 更改时重新渲染。
不建议经常使用 shouldComponentUpdate
函数组件
React.memo
React.memo 是一个高阶组件,所以它的语法如下:
const MyComponent = React.memo(function MyComponent(props) {
/* render using props */
});
const Child = React.memo(function Child() {
console.log('child render');
return <>This is Child Component</>;
});
如果组件在相同的 props 的情况下渲染相同的结果,那么可以通过包装在 React.memo 中调用,以此通过记忆组件渲染结果来提高组件的性能。React.memo 仅检查 props 变更,如果实现中拥有 useState、useReducer或useContext 的 Hook,当 state 或 context 发生变化时,它仍会重新渲染。