Original link: ssshooter.com/2019-03-15-…

I was confused about the use of shouldComponentUpdate. One of the selling points of React is to reduce operations on real nodes by diff virtual node trees, so I used to think that if a node was diff, it would know whether it was updated or not. Diff is based on setState. So shouldComponentUpdate, what does that do?

However, my previous understanding was completely wrong. The reason for this question was that I was not familiar with the React rendering process. Start at the beginning.

setState

React rerenders the page to display your new data. Use the setState method.

After setState is called, the component’s Render method is automatically called, which is why you can see the new data on the page. But whatever you change with setState, even if it’s not on the page, the render will be triggered and the parent component will nest the render from the component.

class Nest extends React.Component {
  render() {
    console.log('inner')
    return <div>Nest</div>}}class App extends React.Component {
  render() {
    console.log('outer')
    return (
      <div>
        <button
          onClick={()= > {
            this.setState({
              anything: 1,
            })
          }}
        >
          setState
        </button>
        <Nest />
      </div>)}}Copy the code

So in this case, click the button, and the Render function runs as expected, even though the modified anything is never present or even defined. Each time the button is clicked, the code above prints outer and then inner.

render

What does Render generate? Usually people write JSX, so it looks like a “DOM”, but in fact, the website tells you prominently that this is actually a function.

// jsx
const element = <h1 className="greeting">Hello, world!</h1>
// Babel translates to a function that the browser can run
const element = React.createElement(
  'h1',
  { className: 'greeting' },
  'Hello, world! '
)
Copy the code

Because React components are nested, the Render function generates a tree of nodes describing the structure of the application and stores it in memory. On the next rendering, a new tree is generated and the two trees are compared.

diff

The official definition is called Reconciliation. React is the algorithm used to compare two node trees and determine which parts of the tree need to be updated.

After the difference between the two trees is determined, the actual nodes are manipulated in different places, so that the interface you see is finally changed at this step. React was popular because of its efficient DOM manipulation method.

shouldComponentUpdate

Finally shouldComponentUpdate, which is a component method that intercepts component rendering. Let’s use an example to explain what is called “intercept rendering”.

class Nest extends React.Component {
  shouldComponentUpdate = (a)= > { // <---- note here
    return false
  }
  render() {
    console.log('inner')
    return <div>Nest</div>}}class App extends React.Component {
  render() {
    console.log('outer')
    return (
      <div>
        <button
          onClick={()= > {
            this.setState({
              anything: 1,
            })
          }}
        >
          setState
        </button>
        <Nest />
      </div>)}}Copy the code

Similar to the previous example, but when we add shouldComponentUpdate to the child component and click the button, the result is ————

ShouldComponentUpdate () {shouldComponentUpdate () {shouldComponentUpdate ();}

Of course you don’t do this, because if you always return false, the component (and all of its children will never be updated because the render function is not running) will never be updated.

The common operation is to check if the props and state of this component have changed in shouldComponentUpdate, like this:

class Nest extends React.Component {
  shouldComponentUpdate = (nextProps, nextState) = > {
    return (
      !shallowEqual(this.props, nextProps) || ! shallowEqual(this.state, nextState)
    )
  }
  render() {
    console.log('inner')
    return <div>Nest</div>}}Copy the code

In this way, the props and state can be compared. Why not? Because that would probably be less efficient than just running render all the way through…

React provides the PureComponent directly because the above operation is so common:

class Nest extends React.PureComponent {
  render() {
    console.log('inner')
    return <div>Nest</div>}}Copy the code

Using PureComponent will have the same effect as above and omit shouldComponentUpdate.

When will it be used?

PureComponent improves performance! So replace all components with PureComponent!

Of course this is wrong.

For components that you know do not need to modify, always return false directly. You may not know it, but don’t use PureComponent for components that you know need to be modified.

Because, as mentioned above, PureComponent requires two shallow comparisons, and shallow comparisons take time. If you know the component is 100% going to change, why waste time doing them?

So use PureComponent for components that need less modification.

conclusion

To summarize the above, the whole process is basically as follows:

Part of this article has my own understanding, if there is no rigorous place in the article, please point out in the comment section, thank you for reading.

References:

Reactjs.org/docs/faq-in…

Reactjs.org/docs/optimi…

Github.com/xitu/gold-m…

Cdb.reacttraining.com/react-inlin…