react - Performance Optimization

Posted by Volte6 on Wed, 26 Jan 2022 14:02:01 +0100

setState

Update data

  • setState() is a way to update data asynchronously
  • Note: when using this syntax, the following setState() does not depend on the previous setState()
1. When you call setState When I was young, React.js It will not be modified immediately state ((why)
2. Instead, the object is placed in an update queue
3. The new state will be extracted from the queue and merged into the queue later state And then trigger the component update.
  • You can call setState() multiple times and only trigger a re rendering
this.state = { count: 1 }
this.setState({
	count: this.state.count + 1
})
console.log(this.state.count) // 1

When using react JS, there is no need to worry about the performance problems caused by multiple setState.

Recommended grammar

  • Recommendation: use the setstate ((prestate) = > {}) syntax

  • Parameter prestate: react JS will pass the result of the last setState into this function

this.setState((preState) => {
    return {
    	count: preState.count + 1
    }
})
console.log(this.state.count) // 1

This syntax is still asynchronous, but state can get the latest state, which is suitable for calling setState multiple times

Second parameter

  • Scene: perform an operation immediately after the status update (page re rendering)
  • Syntax: setState(updater[, callback])
this.setState(
	(state) => ({}),
	() => {console.log('This callback function will be executed immediately after the status update')}
)
this.setState(
	(state, props) => {},
	() => {
		document.title = 'to update state Title after:' + this.state.count
	}
)

JSX syntax conversion process

  • JSX is just the syntax sugar (simplified syntax) of the createElement() method
  • The JSX syntax is compiled into the createElement() method by the @ Babel / preset react plug-in
  • React element: an object that describes what you want to see on the screen
  • In the process of use, JSX can be used as an object.

Component update mechanism

  • Two functions of setState(): 1 Modify state 2 Update component (UI)
  • Pass: when the parent component is re rendered, the child component is also re rendered. However, only the current component subtree (the current component and all its subcomponents) is rendered

Component performance optimization

  1. Function first
  2. performance optimization

Reduce state

  • Reduce state (data): only store data related to component rendering (such as count / list data / loading, etc.)
  • Note: do not put the data not to be rendered in the state, such as timer id
  • For this kind of data that needs to be used in multiple methods, it should be directly placed in this
    • this.xxx = 'bbb'
    • this.xxx
class Hello extends Component {
    componentDidMount() {
        // timerId is stored in this instead of state
        this.timerId = setInterval(() => {}, 2000)
    }
    componentWillUnmount() {
    	clearInterval(this.timerId)
    }
    render() { ... }
}

Don't put data irrelevant to rendering into data in vue. Putting it in will cause a lot of unnecessary rendering.

Avoid unnecessary re rendering

  • Component update mechanism: the parent component update will cause the child components to be updated. This idea is very clear

  • Problem: the sub components will be re rendered without any change (the received props have not changed)

  • How to avoid unnecessary re rendering?

  • Solution: use hook function shouldComponentUpdate(nextProps, nextState)

  • Function: determines whether the component is re rendered by the return value. Returning true means re rendering, and false means no re rendering

  • Trigger timing: the hook function in the update phase, which is executed before the component is re rendered (shouldcomponentupdate = > render)

class Hello extends Component {
    shouldComponentUpdate() {
        // Depending on the condition, decide whether to re render the component
        return false
    }
    render() {...}
}

Pure component

  • Pure component: react Purecomponent and react Component functions are similar
  • Difference: the shouldComponentUpdate hook is automatically implemented in PureComponent, and manual comparison is not required
  • Principle: the pure component determines whether to re render the component by comparing the props and state values twice before and after
class Hello extends React.PureComponent {
    render() {
        return (
        	<div>Pure component</div>
        )
    }
}

Pure components may only be used for performance optimization. Do not use pure components for all components, because pure components need to consume performance for comparison

Pure component comparison - value type

  • Note: the internal comparison of pure components is shallow comparison

  • For value types: compare whether two values are the same (direct assignment, no pit)

let number = 0
let newNumber = number
newNumber = 2
console.log(number === newNumber) // false
state = { number: 0 }
setState({
  number: Math.floor(Math.random() * 3)
})
// PureComponent internal comparison:
abreast of the times state.number === Last time state.number // false, re render the component

Pure component comparison - reference type

  • Note: the internal comparison of pure components is shallow comparison
  • For reference types: only compare whether the reference (address) of the object is the same
const obj = { number: 0 }
const newObj = obj
newObj.number = 2
console.log(newObj === obj) // true
state = { obj: { number: 0 } }
// Wrong practice
state.obj.number = 2
setState({ obj: state.obj })
// PureComponent internal comparison:
abreast of the times state.obj === Last time state.obj // true, do not re render the component

Best practices for pure components:

Note: when the attribute value in state or props is a reference type, you should create new data instead of directly modifying the original data!

// correct! Create new data
const newObj = {...state.obj, number: 2}
setState({ obj: newObj })
// correct! Create new data
// Do not use the push / unshift of the array to directly modify the current array
// Instead, you should use methods such as concat or slice to return a new array
this.setState({
	list: [...this.state.list, {New data}]
})

Virtual DOM and diff algorithm

  • The idea of React updating the view is to re render the view whenever the state changes
  • Question: when only one DOM element in a component needs to be updated, do you have to re render the contents of the whole component to the page?
  • Ideal state: partial update, only update the changed places.
  • Question: how is React partially updated? Virtual DOM with Diff algorithm

Virtual DOM

Virtual DOM: the virtual DOM uses javascript objects to describe the DOM structure

  • Why virtual DOM?
    • Because the cost of operating real DOM is very expensive. Any DOM object has many properties
    • Most of the properties in DOM are not what we need to pay attention to
  • Virtual DOM:
    • js object is used to describe a DOM structure. In the react framework, a DOM object is described and a virtual DOM is used
    • All page updates can be reflected on js objects first. Obviously, the speed of operating js objects in memory is much faster, and there is no need to redraw and reflow
    • After the update, the final js object is mapped into a real DOM and handed over to the browser for drawing.

DIFF algorithm

In react, diff algorithm is used to decide how to update the content in the view

diff algorithm - Chinese documents

Resources: how to implement a virtual DOM

Examples of diif algorithm

  • If the root element types of the two trees are different, React will destroy the old tree and create a new tree
// Old tree
<div>
  Zhang San
</div>

// New tree
<span>
  Zhang San
</span>
  • For React DOM elements of the same type, if only the attributes are different, only different attributes are updated
// used
<div className="before" title="stuff"></div>
// new
<div className="after" title="stuff"></div>
Update only: className attribute

// used
<div style={{color: 'red', fontWeight: 'bold'}}></div>
// new
<div style={{color: 'green', fontWeight: 'bold'}}></div>
Update only: color attribute
  • Adding nodes
// used
<ul>
  <li>first</li>
  <li>second</li>
</ul>

// new
<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>
// Add < li > third to the virtual DOM</li>



// Low efficiency
// Old [a,b]
<ul>
  <li>a</li>
  <li>b</li>
</ul>
// New [c,a,b]
<ul>
  <li>c</li>
  <li>a</li>
  <li>b</li>
</ul>
// React will change each child node and will not guarantee that < li > a < / Li > < li > b < / Li > will not change
  • Case with key
// used
<ul>
  <li key="2015">a</li>
  <li key="2016">b</li>
</ul>

// new
<ul>
  <li key="2014">c</li>
  <li key="2015">a</li>
  <li key="2016">b</li>
</ul>

// react moves elements according to the unique key
// It is recommended to use the key attribute when traversing data

How to update DOM in react

  1. The virtual DOM(JavaScript) object structure is used to represent the structure of the DOM tree, and the real DOM tree is rendered according to the virtual dom

  2. When the state changes, reconstruct a new object tree. Then compare the new tree with the old tree and record the difference between the two trees (diff algorithm)

  3. Apply the differences recorded in step 2 to the real DOM tree built in step 1, and the view is updated

Topics: React