What is thePureComponent
?
PureComponent is a subclass of Component that automatically loads shouldComponentUpdate. ShouldComponentUpdate performs a shallow comparison between the props and the props when the component is updated. If the props and the state are not changed, the Render function is not executed. This is optimized for react performance.
So PureComponent works by performing shallow comparisons to optimize component performance.
PureComponent
What problem was solved?
PureComponent uses shallow comparisons to solve the problem of performance degradation caused by repeated calls to the Render function when state or props are invariant.
PureComponent
和 Component
What is the difference between?
PureComponent automatically executes shouldComponentUpdate (). The performance of components is optimized by shallow comparison of shallowEqual. Component should call shouldComponentUpdate itself to optimize the Component.
(2) PureComponent affects not only itself but also its children. So the best case for using PureComponent is to present components.
A: Parent and child components inherit from Component and are updated whenever changes are made.
B: Both parent and child components inherit from PureComponent, depending on their props and state.
C: The parent Component inherits PureComponent and the child Component inherits Component if the parent Component’s state or props does not change and the child Component’s props does. The child component does not trigger the update because the parent component is not updated and the child component is affected by it.
D: The parent Component inherits Component, and the child Component inherits PureComponent, depending on their props and state.
(3) If the reference type (array or object), it will need to change the address of the reference before rendering.
(4) If the props and state change each time, it is recommended to use Component because shallow comparisons of PureComponent take time.
(5) If shouldComponentUpdate (), execute it; if not, check whether it is PureComponent; if so, shallow compare.
PureComponent
Advantages and disadvantages:
Advantages:
There is no need for developers to use shouldComponentUpdate to improve performance, it does its own shallow comparison.
disadvantages
For props or state of a reference type, there could be a problem with judging and not triggering the render.
Compare when it is a basic typePureComponent
andComponent
Here’s an example:
import React, { Component, PureComponent } from 'react';
class DiffComponent extends Component {
render() {
return (
<div>Compare PureComponent and Component<div style={{ display: 'flex' }}>
<div style={{ marginRight: 200}} >
<PureComp />
</div>
<NormalComp />
</div>
</div>); }}export default DiffComponent;
class PureComp extends PureComponent {
constructor() {
super(a);this.state = {
text: 'true'./ / reference value
};
console.log('pure-constructor');
}
changeState = () = > {
this.setState({
text: 'false'}); };render() {
console.log('pure-render'.this);
return (
<div>
PureComponent
<button onClick={this.changeState}>Click</button>
<div>{this.state.text}</div>
</div>); }}class NormalComp extends Component {
constructor() {
super(a);this.state = {
text: 'true'./ / reference value
};
console.log('normal-constructor');
}
changeState = () = > {
this.setState({
text: 'false'}); };render() {
console.log('normal-render'.this);
return (
<div>
normalComponent
<button onClick={this.changeState}>Click</button>
<div>{this.state.text}</div>
</div>); }}Copy the code
As you can see, PureComp inherits from PureComponent and NormalComp inherits from Component. Both components have a state of text, which can be changed to false by clicking the button.
Comparative analysis:
(1) During component initialization:
To initialize PureComp, type pure-constructor followed by pure-render.
To initialize NormalComp, type normal-constructor and normal-render.
(2) When the button is clicked:
PureCom components:
The first time you click the button, the interface value is changed to false, execute render, and print pure-render.
Pure-render is no longer output after clicking the button several times, indicating that the render method is no longer executed.
While NormalComp components:
The first time you click the button, the interface value is changed to false, execute the render method, and print normal-render.
“Normal-render” will be output every time you click the button. The render method is executed each time.
Conclusion:
This is the internal optimization of PureComponent, which makes a superficial comparison between state and props.
For NormalComp components, the inherited Component executes the Render method whenever state changes.
If you want to optimize your judgment by not executing Render multiple times, you can compare it in the shouldComponentUpdate lifecycle.
Return true to render; return false to render not.
The same applies to string, number, and other primitive types
Comparison when a reference type is usedPureComponent
andComponent
Same as above, except we add arR to state and render the value of arR in the Render method.
import React, { Component, PureComponent } from 'react';
class DiffComponent extends Component {
render() {
return (
<div>Compare PureComponent and Component<div style={{ display: 'flex' }}>
<div style={{ marginRight: 200}} >
<PureComp />
</div>
<NormalComp />
</div>
</div>); }}export default DiffComponent;
class PureComp extends PureComponent {
constructor() {
super(a);this.state = {
arr: [1].// Type reference
};
console.log('pure-constructor');
}
changeState = () = > {
let {arr} = this.state;
arr.push('2');
this.setState({
arr
});
};
render() {
console.log('pure-render'.this.state);
return (
<div>
PureComponent
<button onClick={this.changeState}>Click</button>
{
this.state.arr.map(item=>{
return <div>{item}</div>})}</div>); }}class NormalComp extends Component {
constructor() {
super(a);this.state = {
arr: [1].// Type reference
};
console.log('normal-constructor');
}
changeState = () = > {
let {arr} = this.state;
arr.push('2');
this.setState({
arr
});
};
render() {
console.log('normal-render'.this.state);
return (
<div>
normalComponent
<button onClick={this.changeState}>Click</button>
{
this.state.arr.map(item=>{
return <div>{item}</div>})}</div>); }}Copy the code
Comparative analysis:
(1) Construct and Render are executed sequentially when components are initialized. PureComponent is no different from Component.
(2) When the button is clicked:
PureComp components:
The console does not output anything when the button is clicked, and the Render method is not executed.
NormalComp components:
Every time you click the button, the console prints normal-render. The interface values also change, indicating that the Render method is executed each time.
Conclusion:
The PureComp component does not re-render render because the arR reference type in state has not changed during shallow comparison, so render is not executed.
If you change changeState to read like this and change the arR reference, the PureComponent executes the Render method.
changeState = () = > {
let newArr = [...this.state.arr];
newArr.push('2');
this.setState({
arr: newArr
});
};
Copy the code
PureComponent
Source code analysis
PureComponent source code:
export default function PureComponent (props, context) {
Component.call(this, props, context)
}
PureComponent.prototype = Object.create(Component.prototye)
PureComponent.prototype.contructor = PureComponent
PureComponent.prototype.shouldComponentUpdate = shallowCompare
function shallowCompare (nextProps, nextState) {
return! shallowEqual(this.props, nextProps) || ! shallowEqual(this.state, nextState)
}
Copy the code
As you can see from the source code, PureComponent inherits Component and overrides the shouldComponentUpdate method. ShouldComponentUpdate just returns the value of the shallowEqual method.
Here’s a look at the shallowEqual method source code
function shallowEqual(objA: mixed, objB: mixed) :boolean {
if (is(objA, objB)) {
return true;
}
if (typeofobjA ! = ='object' || objA === null ||
typeofobjB ! = ='object' || objB === null) {
return false;
}
const keysA = Object.keys(objA);
const keysB = Object.keys(objB);
if(keysA.length ! == keysB.length) {return false;
}
// Test for A's keys different from B.
for (let i = 0; i < keysA.length; i++) {
if(! hasOwnProperty.call(objB, keysA[i]) || ! is(objA[keysA[i]], objB[keysA[i]]) ) {return false; }}return true;
}
Copy the code
The shallowEqual function does the following:
(1) The is function is used to compare the two parameters to determine whether they are the same. If they are the same, the value of the basic data type is the same, and the reference object is the same
(2) If two parameters are different, check whether at least one of the two parameters is not a reference type and return false. If both parameters are reference type objects, proceed with the following comparison:
(3) Determine whether two objects of different reference types are the same
Keys = keys = keys = keys = keys = keys = keys = keys = keys = keys = keys
The IS method is implemented as follows
function is(x, y) {
// SameValue algorithm
if (x === y) {
// exclude +0 === -0
// x ! == 0 || y ! If lambda is equal to lambda is equal to 0, then x and y are either 0 or negative 0
// 1 / x === 1 / y Equals equals minus Infinity is true
returnx ! = =0|| y ! = =0 || 1 / x === 1 / y;
} else {
// x ! == x determines whether x is a NaN and y. Similarly, if x and y are both NaN, return true
returnx ! == x && y ! == y; }}Copy the code
conclusion
To summarize, PureComponent is a subclass that inherits Component and executes shouldComponentUpdate for shallowEqual comparisons to solve Component performance problems.
Next time we’ll simply implement a PureComponent.