创建项目
$ npx create-react-app react-try
情景一:shouldComponentUpdate
Child.js
import React from 'react';
class Child extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log('child did mount');
}
componentWillUnmount() {
console.log('child will mount');
}
render() {
console.log('child render');
return (
<div>
<h1>This is Child</h1>
</div>
);
}
}
export default Child;
Parent.js
import React from 'react';
import Child from './Child';
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
this.handleTime = this.handleTime.bind(this);
}
componentDidMount() {
console.log('parent did mount');
}
componentWillUnmount() {
console.log('parent will mount');
}
handleTime() {
this.setState({
date: new Date()
})
}
render() {
console.log('parent render');
return (
<div>
<h1>This is Parent</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
<button onClick={this.handleTime}>更新时间</button>
<Child />
</div>
);
}
}
export default Parent;
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Parent from './components/Parent';
ReactDOM.render(
<React.StrictMode>
<Parent />
</React.StrictMode>,
document.getElementById('root')
);
页面初始渲染时,控制台输出:
parent render
child render
child did mount
parent did mount
点击更新时间按钮时,控制台输出:
parent render
child render
问题:我们发现子组件Child.js没有任何变化,也重新渲染了。这是一个优化的点。
我们在Child.js中添加以下代码:
// 组件是否应该更新,默认返回的是true,这里我们返回false,不进行子组件的重新渲染。
shouldComponentUpdate() {
return false;
}
组件卸载顺序为:
parent will mount
child will mount
情景二:shouldComponentUpdate
我们子组件里,依赖一个父组件里传过来的属性number,我们希望number改变时,才去渲染子组件。而不是父组件里每次更新,子组件都会重新渲染。
Child.js
import React from 'react';
class Child extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
console.log('child did mount');
}
componentWillUnmount() {
console.log('child will mount');
}
render() {
console.log('child render');
return (
<div>
<h1>This is Child</h1>
<p>from parent number: {this.props.number}</p>
</div>
);
}
}
export default Child;
Parent.js
import React from 'react';
import Child from './Child';
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {
date: new Date(),
number: 0,
};
this.handleTime = this.handleTime.bind(this);
this.handleNumber = this.handleNumber.bind(this);
}
componentDidMount() {
console.log('parent did mount');
}
componentWillUnmount() {
console.log('parent will mount');
}
handleTime() {
this.setState({
date: new Date()
})
}
handleNumber(){
this.setState((state, props) => {
return {
number: state.number + 1
}
});
}
render() {
console.log('parent render');
const number = this.state.number;
return (
<div>
<h1>This is Parent</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
<p>number: {number}</p>
<Child number={number}/>
<div>
<button onClick={this.handleTime}>更新时间</button>
<button onClick={this.handleNumber}>更新数字</button>
</div>
</div>
);
}
}
export default Parent;
父组件中,我们调用更新时间、更新数字时,子组件都去重新渲染了。怎么优化呢?
Child.js
//我们判断下次接受的新属性是否与当前属性值相等,如果相等,我们不去重新渲染
shouldComponentUpdate(nextProps) {
if(nextProps.number === this.props.number){
return false;
}
return true;
}
这时我们再点击更新时间时,子组件不会渲染,只有点击更新数字时,子组件才会渲染。
More
浅谈React性能优化的方向
https://juejin.cn/post/6844903865926549511
React 性能优化,你需要知道的几个点
https://www.jianshu.com/p/333f390f2e84