The necessity of using immutable. js to maximize react performance optimization, reactimmutable. js
A line of code is better than a thousand words. This article mainly describes how to optimize react performance step by step. Why use immutable. js. It is no exaggeration to say. With immutable. js (of course there are other implementation libraries ).. In order to maximize the performance of react! This article is very suitable for you if you have used react for a while without immutable. Let me start!
1. For react, if the parent component has multiple child components
Imagine a scenario where a parent component contains a large number of child components. Then, this parent component re-render. Do the following sub-components have to follow re-render. However, many sub-components are innocent! The props and state of many sub-components have not changed !! Although the diff algorithm of virtual dom is fast, the performance is not so wasteful! The code below
1). the original code is as follows:
The following is the code of the parent component .. Enter name and age, and display name and age cyclically
Export default class extends Component {constructor (props) {super (props) this. state = {name: "", age: "", persons: []} render () {const {name, age, persons} = this. state return (<div> <span> name: </span> <input value = {name} name = "name" onChange = {this. _ handleChange. bind (this) }></input> <span> age: </span> <input value = {age} name = "age" onChange = {this. _ handleChange. bind (this) }></input> <input type = "button" onClick = {this. _ handleClick. bind (this)} value = "OK"> </input> {persons. map (person, index) => (<Person key = {index} name = {person. name} age = {person. age }></Person>) }</div>) }_ handleChange (event) {this.setstate({{event.tar get. name]: event.tar get. value})} _ handleClick () {const {name, age} = this. state this. setState ({name: "", age: "", persons: this. state. persons. concat ([{name: name, age: age}])}
The following is the sub-component code that simply displays the name and age.
Class Person extends Component {componentWillReceiveProps (newProps) {console. log ('the name of my new props is $ {newProps. name}, age is $ {newProps. age }. My previous props name was $ {this. props. name}, age is $ {this. props. age}: I want to re-render ');} render () {const {name, age} = this. props; return (<div> <span> name: </span> <span> {name} </span> <span> age: </span> <span >{age }</span> </div> )}}
Long Running
Okay. Now, let's take a look at the console:
Oh, it's not hard to find so many reder views. If re-render is required for so many times, the parent component re-render follows re-render. This is a waste of performance, so PureRenderMixin is playing well.
2). PureRenderMixin
Because we use es2015 Component, we do not support mixin anymore, but it doesn't matter. We can use HOCs, which is more admired than mixin. I am free to use the code to show their similarities and differences. since they Are not the focus of this article, you can read these two articles to understand the past and present of React Mixin and Mixins Are Dead. Long Live Composition.
So here we use Pure render decorator to replace PureRenderMixin, the Code is as follows:
Import pureRender from "pure-render-decorator "... @ pureRenderclass Person extends Component {render () {console. log ("I re-render"); const {name, age} = this. props; return (<div> <span> name: </span> <span> {name} </span> <span> age: </span> <span >{age }</span> </div> )}}
Is this the end of the process? It seems so unconvincing. Try it anyway.
Sure enough, you can do the pure render, and render only when the render is required.
Okay. Let's see what's amazing.
@ PureRender
Is es7's Decorators syntax. The above is the same as the below.
Class PersonOrigin extends Component {render () {console. log ("I re-render"); const {name, age} = this. props; return (<div> <span> name: </span> <span> {name} </span> <span> age: </span> <span >{age }</span> </div>) }} const Person = pureRender (PersonOrigin)
PureRender is actually a function that accepts a Component. Let's take a look at this Component and return a Component to check its pureRender source code.
function shouldComponentUpdate(nextProps, nextState) { return shallowCompare(this, nextProps, nextState);}function pureRende(component) { component.prototype.shouldComponentUpdate = shouldComponentUpdate;}module.exports = pureRender;
PureRender is simple, that is, it overwrites the shouldComponentUpdate of the passed component. The original shouldComponentUpdate is always return ture, but it cannot be used now. I want to use shallowCompare to compare the shallowCompare code and its simplicity.
function shallowCompare(instance, nextProps, nextState) { return !shallowEqual(instance.props, nextProps) || !shallowEqual(instance.state, nextState);}
Clear at a glance. Take the current props & state and the props & state to be passed in respectively, and use the shallowEqual ratio. If props & state are the same, return false. Is it perfect? No .. This is just the beginning. The problem lies in shallowEqual.
3). shallowEqual Problems
Bug caused by shallowEqual
Many times, when the parent component transmits props to the child component, it may pass a complex type, for example, we can change it.
Render () {const {name, age, persons} = this. state return (<div>... omitted ..... {persons. map (person, index) =>( <Person key = {index} detail = {person }></Person>) }</div> )}
Person is a complex type. This is a hidden danger. Before demonstrating the hidden danger, let's talk about shallowEqual. shallowEqual actually only compares the first layer of subattributes of props, just like the above Code, props is as follows
{ detail:{ name:"123", age:"123"}}
It only compares props. detail === nextProps. detail
So the question is, go to the code
If I want to modify detail, consider either of the following situations:
Case 1,I modify the detail content without modifying the reference of detail.
This will cause a bug. For example, if I modify detail. name, because the reference of detail is not changed, props. detail = nextProps. detail is still true.
So we must modify the reference of detail for security reasons (this is what redux reducer does)
Case 2,I modified the reference of detail.
Although there are no bugs, it is easy to kill by mistake. For example, if the content of the new and old detail is the same, wouldn't it be necessary to render it. So it is still not perfect. You may say that it is better to use deep comparison, but deep comparison and consumption performance should be ensured by recursion that each sub-element is the same.
This is just to say that immutable is not used to cause various, and next articles. I will explain how to use immutable. j.
The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.