SetState and React performance optimization

  • Synchronization and asynchrony of setState
    • Why use setState
    • SetState Asynchronous update
    • How do I get asynchronous results
    • Is setState necessarily asynchronous?
    • Source code analysis
  • SetState merger
    • Data consolidation
    • Consolidation of multiple states
  • React Update mechanism
    • React Update mechanism
    • React Update process
  • React Performance Optimization
    • The optimization of the key
    • The render function is called
    • shouldComponentUpdate
    • PureComponent
    • ShallowEqual method
    • Advanced component Memo
  • React Brain maps

Synchronization and asynchrony of setState

1. Why use setState

  • In development we are notCannot be modified directly stateThe value ofLet the interface update:
    • Because we modified itstateAnd then hopefullyReactAccording to the latestStateTo re-render the interface, but this way modificationReactDidn’t know the data had changed
    • ReactThere is no implementation likeVue2In theObject.definePropertyorVue3In theProxyTo listen for changes in data
    • We have to go throughsetStateTo informReactThe numbers have changed
  • Confusion: not implemented in the componentsteStateMethod, why can be called?
    • The reason is simple:setStateMethods fromComponent δΈ­inherited

2. SetState updates asynchronously

SetState is updated asynchronously


  • whysetStateWhat about asynchronous design?
    • setStateDesigned to be asynchronous actually beforeGitHubThere was a lot of discussion on
    • React core member (and Redux writer) Dan Abramov also has a response for those interested
  • Simple summary:setStateDesigned to be asynchronous, yesSignificantly improved performance
    • If every time I callsetStateAll have an update, so that meansrenderFunctions are frequently re-rendered by the call interface, which is inefficient
    • The best approach is to get multiple updates and then batch them
  • If the synchronization updatesstateBut it has not been carried outrenderDelta function, thenstateandpropsOut of sync
    • stateandpropsFailure to maintain consistency can cause a lot of problems in development

3. How do I get asynchronous results

  • How to getsetStateAsynchronous updatestateAfter the value?
  • A:setStateThe callback
    • setStateReceives two arguments: the second argument is the callback function (callback), the callback function will run instateExecute after update

  • Method 2:componentDidUpdateLife cycle function

3. Is setState necessarily asynchronous?

❝

  • There are actually two cases
  • In the component life cycle or React composite event,setStateIs asynchronous
  • insetTimeouOr native DOM events,setStateIs synchronous

❞

  • Verification 1: insetTimeoutUpdate – > Synchronize Update in

  • Verification two: in the nativeDOMEvents – > Synchronize updates

4. Source code analysis





SetState merger

1. Data consolidation

  • throughsetStateTo modifymessage, it isNot to other people stateIs having an impact
    • Source code is actually on the “original object” and “new object” merge

2. Consolidation of multiple states

  • When ourMultiple callsthesetState.It only works one more timestate

  • setStateTo accumulate when merging:Pass the function to setState, used the previous timestateThe values in the




React Update mechanism

1.React Update mechanism

  • We’ve seen that beforeReactRendering process:

  • What about the React update process?

  • React Process

2.React Updates the process

  • React calls the Render method of React when the props or state changes, creating a different tree

  • React needs to determine how to effectively update the UI based on the difference between the two different trees:

  • If one tree is completely updated with reference to another, then even the most advanced algorithm has a complexity of O(n)
    3 ^ 3
    ), where n is the number of elements in the tree

    • If theReactUsing the algorithm, then show1000The number of computations to be performed on the elementOne billionMagnitude range of
  • This overhead is too expensive, and React’s update performance becomes inefficient

  • React optimizes this algorithm to O(n). How?

    • Nodes at the same level are compared with each other, not across nodes

    • Different types of nodes produce different tree structures

    • In development, keys can be used to specify which nodes remain stable under different renders

Case 1: Compare different types of elements

  • When nodes have different elements, React disassembles the existing tree and creates a new one:

    • When an element changes from to , from

      to

      , or from


    • When a tree is unmounted, the corresponding DOM node is also destroyed, and the component instance executes the componentWillUnmount() method

    • When a new tree is created, the corresponding DOM node is created and inserted into the DOM, and the component instance executes the componentWillMount() method followed by the componentDidMount() method

  • Such as the following code change:

    • React destroys the Counter component and reloads a new one instead of reusing the Counter

Case 2: Compare elements of the same type

  • When comparing two React elements of the same type, React preserves the DOM node and updates only the changed properties
  • Such as the following code change:
    • By comparing these two elements,React I know I just need to fix itDOMOn the elementclassNameattribute

  • Such as the following code change:

    • When updating the style property, React updates only the properties that have changed.

    • By comparing the two elements, React knows that it only needs to change the color style on the DOM element, not the fontWeight

  • If it is a component element of the same type:

    • Component will remain the same, will React to update the component props, and invoke componentWillReceiveProps () and componentWillUpdate () method

    • Next, the render() method is called, and the diff algorithm recurses over the previous result as well as the new one

Case 3: Recurse on child nodes

  • By default, React iterates through lists of both child elements while recursively iterating through the child elements of a DOM node. When a difference occurs, a mutation is generated

    • Let’s look at inserting a piece of data at the end: πŸ‘‡

    • The first two comparisons are identical, so no mutation will occur

    • For the final comparison, a mutation is generated and inserted into the new DOM tree

  • But if we insert a piece of data in front of it:

    • React produces a mutation on each child element instead of holding it<li> Interstellar </li> ε’Œ <li> </li>Of the same
    • This inefficient way of comparing results in performance problems




React Performance Optimization

1. The optimization of the key

  • As we walked through the list earlier, we were always prompted with a warning to join onekeyProperties:

  • Method 1: Insert data in the last position

    • This situation, whetherkeyDoesn’t mean much
  • Method 2: Insert data in front

    • This practice in nokey In the case of all<li>All need to be modified
  • In the following example: when the child element (in this case li) has a key

    • React uses keys to match the child elements of the original tree with the child elements of the latest tree:

    • In the following scenario, keys are elements 111 and 222Just displacementAnd don’tNeed to make any modifications

    • willkeyfor333Insert the element in the first place

Key notes:

  • keyIt should be unique
  • keyDo not use random numbers (random numbers will regenerate a number in the next render)
  • useindexAs akeyThere is no optimization for performance

The render function is called

  • Let’s use an earlier nested example:

    • In the App, we added a counter code
  • When +1 is clicked, the App’s render function is called again

    • When the render function of the App is called, the render function of all the child components will be called again

  • So, we can think about, in the future development, whenever we modify the data in the App, all the sub-components need to be rebuiltrender,diffAlgorithm, performance is necessarily very low:
    • In fact, many components do not have to be rebuiltrender
    • They should call render with the premise that they call their render methods when the dependent data (state, props) changes
  • How to controlrender Is the method called or not?
    • throughshouldComponentUpdateMethods can be

3.shouldComponentUpdate

React provides a life cycle method shouldComponentUpdate (in many cases, we call it SCU for short), which takes arguments and returns values; Controls whether the render** method is called on the current class component object

  • This method takes two parameters:
    • A parameter:nextProps After modification, the latestporps attribute
    • Parameters of the two:nextStateAfter modification, the lateststateattribute
  • The methodThe return valueIs a Booolan type
    • The return value istrue, then you need to callrendermethods
    • The return value isfalse, then no call is requiredrendermethods
  • Let’s say we add one to our AppmessageProperties:
    • JSXAnd in theThere is no dependencethismessage, thenIts changes should not cause re-rendering
    • But bysetStateModify thestateThe value of, so finallyrenderThe method is called again
// Determines whether the current class component object calls the Render method
// Parameter one: the latest props
// Parameter two: the latest state
shouldComponentUpdate(nextProps, nextState) {
  // The default is: return true
  // Do not call render if you do not need to render on the page
  return false
}
Copy the code

4.PureComponent

  • If all the classes, we need to implement them manuallyshouldComponentUpdate, which will add a lot of work for us developers
    • Let’s think about whereshouldComponentUpdateIn theWhat are the purposes of judgment?
    • propsorstateTo determine whether the data has changedshouldComponentUpdatereturntrue ζˆ– false
  • In fact,ReactThat was taken into account, soReactIt has been implemented for us by default, how to implement it?
    • Class inherits from PureComponent
    • It’s going to happen internallyShallow contrastThe lateststate ε’Œ porpsIf there are no dependencies within the componentporpsorstateWill not callrender
    • Problem solved: for example, some child components do not depend on the parent componentstateorprops, but it is calledrenderfunction

5. ShallowEqual method

In this method, call! shallowEqual(oldProps, newProps) || ! ShallowEqual (oldState, newState), this shallowEqual is shallow comparison:

6. Advanced component Memo

  • How does a functional component solve the render problem: rerender render without relying on state or props

  • We need to use a higher-order component memo:

    • We wrap the previous Header, Banner, and ProductList with the memo function

    • Footer does not use the memo function to wrap;

    • The net effect is that when counter is changed, the Header, Banner, ProductList functions are not re-executed, but the Footer functions are re-executed

import React, { PureComponent, memo } from 'react'

// MemoHeader: no dependencies, will not be called render again
const MemoHeader = memo(function Header() {
  console.log('Header called ')
  return <h2>I'm a Header component</h2>
})
Copy the code


React Brain maps

πŸ† nuggets technical essay | double festival special articles