They are almost identical, but PureComponent shouldComponentUpdate via a shallow comparison of prop and state, and in some cases PureComponent can be used to improve performance
1. ShallowEqual is a function in the React source code, and it does something we should do in shouldComponentUpdate to check whether it is a PureComponent
if (this._compositeType === CompositeTypes.PureClass) { shouldUpdate = ! shallowEqual(prevProps, nextProps) || ! shallowEqual(inst.state, nextState); }Copy the code
So what we’re doing is we’re checking to see if state has changed (same thing with prop) to decide whether to rerender, and we’re doing this in a Component that inherits Component, and this.state.person is an object, and you can see, The object is not rerender if the reference is not changed, so we can optimize it with shouldComponentUpdate, which returns false to render and true to render. Returns true by default
shouldComponentUpdate(nextProps, nextState) {
return(nextState.person ! = =this.state.person);
}
Copy the code
2. In some cases, PureComponent can be used to improve performance. Practice is the test
3. The following shows an IndexPage component with a state of isShow that can be changed with a button click: The first time you click on the button the render output will render and the interface will change from showing False to showing true. However, when you click on a component that inherits from PureComponent, Render is no longer output, and when the Component inherits from Component it still outputs render and re-renders, which is a reflection of internal optimization in the PureComponent
4. The same applies to string, number and other basic data types, because basic data types change the value even if it changes
import React, { PureComponent } from 'react';
class IndexPage extends PureComponent{
constructor() {
super(a);this.state = {
isShow: false
};
console.log('constructor');
}
changeState = (a)= > {
this.setState({
isShow: true})}; render() {console.log('render');
return (
<div>
<button onClick={this.changeState}>Click on the</button>
<div>{this.state.isShow.toString()}</div>
</div>); }}Copy the code
5. When this.state.arr is an array and the component inherits from PureComponent, the initialization output is still constructor and render, but nothing changes when the button is clicked and no render is output. But as we can see from the comment below, the value of the arr we want to modify changes every time the button is clicked. This value will modify this.state.arr, but because the array reference in PureComponent does not change, it is not rendered. This.state. arr is also not updated, because after this.setstate (), the value is updated at render time, which is involved in this.setstate ()
6. However, when this Component inherits from Component, the initialization output is still constructor and render, but when the button is clicked, the interface changes. We print the arR value output and render each time the button is clicked, proving that it has been rerendered. The value of this.state.arr has been updated, so we can see the change in the interface
import React, { PureComponent } from 'react';
class IndexPage extends PureComponent{
constructor() {
super(a);this.state = {
arr: ['1']};console.log('constructor');
}
changeState = (a)= > {
let { arr } = this.state;
arr.push('2');
console.log(arr);
/ / / "1", "2"
/ / / "1", "2", "2"]
// ["1", "2", "2", "2"]
/ /...
this.setState({
arr
})
};
render() {
console.log('render');
return (
<div>
<button onClick={this.changeState}>Click on the</button>
<div>
{this.state.arr.map((item) => {
return item;
})}
</div>
</div>); }}Copy the code
The following example uses the extension operator to generate a new array that changes the reference to this.state.arr, so output constructor and render each time the button is clicked. Whether the Component inherits from Component or PureComponent
import React, { PureComponent } from 'react';
class IndexPage extends PureComponent{
constructor() {
super(a);this.state = {
arr: ['1']};console.log('constructor');
}
changeState = (a)= > {
let { arr } = this.state;
this.setState({
arr: [...arr, '2']})}; render() {console.log('render');
return (
<div>
<button onClick={this.changeState}>Click on the</button>
<div>
{this.state.arr.map((item) => {
return item;
})}
</div>
</div>); }}Copy the code
8. The same applies to objects
PureComponent affects not only itself but also its children, so PureComponent is best used to display components
1. We will include an Example child component in the IndexPage component to show how PureComponent affects the child components
2. When a parent Component inherits PureComponent and a child Component inherits Component: The following result is initialized with output constructor, IndexPage Render, example render, but when we click the button the interface does not change because the reference to the this.state.person object does not change, The parent Component is PureComponent. The parent Component doesn’t render at all, so the child Component doesn’t render
3. Parent inherits PureComponent, child inherits PureComponent: Because rendering is not done when the parent does it, it is intercepted, so whether the child is a PureComponent or a Component doesn’t affect the result at all. The interface remains the same
4. When a parent Component inherits Component and a child Component inherits PureComponent: Constructor, IndexPage Render, example Render, but when clicked, only IndexPage Render will appear. Since the parent Component is Component, the parent Component will render. But when the parent passes the value to the child, which is PureComponent, it does a shallow comparison of the prop and finds that the reference to the Person object has not changed, so it will not be rerendered, and the interface display is displayed by the child, so the interface will not change
5. Parent Component inherits Component, child Component inherits Component: Initialization will output constructor, IndexPage render, example render, when we click the button for the first time, the interface changes and will not change since we keep it set to SXT2, IndexPage Render will be printed every time you click, because both parent and child components will render each time
6. So, as stated in article 4 below, if state and prop keep changing, it is still recommended to use Component, and PureComponent is best used as the presentation Component
/ / the parent component
import React, { PureComponent, Component } from 'react';
import Example from ".. /components/Example";
class IndexPage extends PureComponent{
constructor() {
super(a);this.state = {
person: {
name: 'sxt'}};console.log('constructor');
}
changeState = (a)= > {
let { person } = this.state;
person.name = 'sxt2';
this.setState({
person
})
};
render() {
console.log('IndexPage render');
const { person } = this.state;
return (
<div>
<button onClick={this.changeState}>Click on the</button>
<Example person={person} />
</div>); }} // subcomponent import React, {Component} from 'React '; class Example extends Component { render() { console.log('example render'); const { person } = this.props; return(<div>
{person.name}
</div>); }}Copy the code
If an array or object is referenced differently, it will be rendered
4. If prop and state change every time, PureComponent is less efficient than Component because, as you know, shallow comparisons take time
ShouldComponentUpdate (); if shouldComponentUpdate (), execute it; if not, check whether it is a PureComponent; if so, shallow compare
If shouldComponentUpdate returns false, PureComponent should not render; if shouldComponentUpdate returns false, PureComponent should not render. So use shouldComponentUpdate in PureComponent with the following warning:
IndexPage has a method called shouldComponentUpdate(). shouldComponentUpdate should not be used when extending React.PureComponent. Please extend React.Component if shouldComponentUpdate is used.
Should not use shouldComponentUpdate in PureComponent because it is not necessary