Formal learning React (iii) REACTJS performance optimization of Shouldcomponentupdate

Source: Internet
Author: User

Performance optimization

Whenever developers choose to use react in real-world projects, they ask a question: will using react make the project faster, more flexible, and easier to maintain. Furthermore, does the process of re-rendering the interface every time the state data changes will cause a performance bottleneck? Inside react, though, is the ability to minimize expensive DOM operations that cause UI updates every time by using subtle techniques to ensure performance.

Avoid directly acting on the DOM

React implements a layer of virtual DOM, which is used to map the native DOM tree of the browser. This layer of virtual DOM allows react to avoid direct manipulation of the DOM, as the direct manipulation of the browser DOM is much slower than manipulating JavaScript objects. Whenever a component's properties or state changes, react constructs a new virtual DOM in memory to compare it with the old one, to determine if the browser's DOM tree needs to be updated, thus optimizing the performance loss of the rendered DOM as much as possible.

On top of this, react provides the component lifecycle function, which is shouldComponentUpdate called when the component decides to re-render (after the virtual Dom has finished generating the final DOM), and the function gives the developer the right to re-render, which is returned by default. true Represents the default direct departure DOM update:

function(nextProps, nextState) {      return true;}

It is important to note that react will call the function very often, so if you intend to implement the logic of the function yourself, try to ensure performance as much as possible.

For example, if you have a chat app with multiple posts, if only one has changed, if you do this shouldComponentUpdate , react will avoid re-rendering those posts that haven't changed, depending on the situation:

function(nextProps, nextState) {      // TODO: return whether or not current chat thread is different to former one. // 根据实际情况判断当前帖子的状态是否和之前不同}

In short, react avoids expensive DOM operations as much as possible and allows developers to interfere with the behavior.

Shouldcomponentupdate Combat

Here is an example of a component that contains child elements, such as:

Each dot in the graph represents a DOM node, and when a DOM node shouldComponentUpdate returns false (for example, C2), react does not need to update the DOM for it, notice that react does not even call the functions of C4 and C5 nodes at all shouldComponentUpdate !

The C1 and C3 in the figure are shouldComponentUpdate returned true , so react examines the direct child nodes they contain. The most interesting is the C8 node, although the method that calls it shouldComponentUpdate returns true , but react checks that its DOM structure has not changed, so react will not re-render its browser dom.

, react will only re-render C6 for the reason you should understand.

So how do we implement the shouldComponentUpdate function? Suppose you have a component that contains only strings, as follows:

React.createClass({      propTypes: { value: React.PropTypes.string.isRequired }, render: function() { return <div>{this.props.value}</div>; }});

We can simply directly implement the shouldComponentUpdate following:

function(nextProps, nextState) {      return this.props.value !== nextProps.value;}

So far everything is going well, it's easy to deal with the properties and states of the underlying type, and we can implement a mix and inject it into all the components directly using the comparison provided by the JS language, === in fact, react itself has provided a similar: Purerendermixin.

But what if your component has a property or state that is not the underlying type, but a composite type? For example, a JS object {foo: ‘bar‘} :

React.createClass({      propTypes: {        value: React.PropTypes.object.isRequired      },      render: function() {        return <div>{this.props.value.foo}</div>; }});

The kind of thing we just realized in this case is the rest of the shouldComponentUpdate dish:

// 假设 this.props.value 是 { foo: ‘bar‘ }// 假设 nextProps.value 是 { foo: ‘bar‘ },// 但是nextProps和this.props对应的引用不相同this.props.value !== nextProps.value; // true

To fix this problem, the simple and rude method is the value of our direct comparison foo , as follows:

function(nextProps, nextState) {      return this.props.value.foo !== nextProps.value.foo;}

We can certainly determine whether a property or state has actually changed by a deep comparison, but this is very expensive, remember when we just said that shouldComponentUpdate the function was called very often? What's more, it's also very painful for developers to implement a matching depth-ratio logic for each model individually. The most important thing is that if we don't deal with the object-referencing relationship very carefully, it can also bring disaster. For example, the following component:

  React.createclass ({getinitialstate: function () {retur      n {value: {foo:  ' bar '}; }, OnClick: function () {var value = this.state.
           
            value; 
            value.foo + =  ' bar '; //anti-pattern! this.setstate ({value: value});}, Render: function () {return (<div> <innercomponent  Value={this.state. Value}/> <a onclick={this.onclick}>click me</a> </div>); }});
            

Initially, the Innercomponent component is rendered, and it gets the value property of {foo: ‘bar‘} . When the user clicks on the link, the parent component's status is updated to trigger the re-rendering of the { value: { foo: ‘barbar‘ } } innercomponent component because it gets a new property: { foo: ‘barbar‘ } .

It seems like everything is fine, but the problem is that the parent and child components are used to refer to the same object, and when the user triggers the Click event, the prop of Innercomponent will change, so its function will be shouldComponentUpdate called, and if you follow our current shouldComponentUpdate than the logical words, this.props.value.foo and nextProps.value.foo are equal, because in fact, they both refer to the same object Oh ~ So, we will see that the Innercomponent UI is not updated. Hey ~, if you don't believe me, I post the full code:

<! DOCTYPE html><Html><Head><Metacharset="Utf-8" ><Title>demo</Title><!--introducing React Library--<ScriptSrc="Lib/react.min.js" ></Script><!--introducing JSX conversion Library--<ScriptSrc="Lib/jsxtransformer.js" ></Script><!--component Styles--</Head><Body><!--define Containers--<DivId="Content" ></Div><!--declaration script type jsx--><ScriptType="TEXT/JSX" > var innercomponent = React.createclass ({shouldcomponentupdate:function(Nextprops, Nextstate) {ReturnThis.props.value.foo!== NextProps.value.foo; }, Render:function() {Return (<div> {This.props.value.foo} </div>); } });var outcomponent = React.createclass ({getinitialstate:function() {Return {value: {foo:' Bar '}; }, OnClick:function () {var value = span class= "keyword" >this.state.value; Value.foo + =  ' bar '; //anti-pattern! this.setstate ({Value:value}), Render:  () {return (<div> <innercomponent value={this.state.value}/> <a onclick={this.onclick}>click me</a> </div >); } }); React.render (<outcomponent/>, Document.queryselector ( "#content")); </script> </body></HTML>          

Formal Learning React (iii) REACTJS performance optimization shouldcomponentupdate

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.