preface
Recently, I encountered the react component rendering problem for several times in the project. Although the problem was solved successfully, I also found that I was not familiar with the React life cycle, so I found the React document to learn more about it and summarized the following two main knowledge points after re-learning: The React component updates the React component.
Life cycle process
The Life cycle of the React component can be roughly divided into three phases:
- Mount (initialization) phase
- Update (Running) phase
- Unloading phase
DOM mount phase
- DefaultProps: Gives an initial value to the props passed by the parent component
Demo.defaultProps={
demo:"test"
}
Copy the code
- Constructor: initialization of the data, which takes two parameters: props and context. When you want to use these two parameters inside a function, you pass them in with super().
1. Whenever using constructor() you must write super(), otherwise this will point to an error. 2. The value of state can be set directly in the constructor lifecycle. constructor(props) { super(props); State this.state = {}; }Copy the code
-
ComponentWillMount: Used to mount before it is executed only once during the life of the component, at which point setState can be performed
-
ComponentDidMount: For componentDidMount to be executed after the DOM has been successfully rendered. This life cycle allows the real DOM element to be retrieved only once during the life of the component. In addition, the official documentation suggests that this life cycle is suitable for asynchronous requests
Import axios from 'axios' componentDidMount(){document.querySelector(" root") // aixos.get('/demo').then(res=>{}) }Copy the code
Why is it officially recommended to make asynchronous requests in the componentDidMount life cycle?
The normal logic is that the earlier the creation lifecycle, the better. For example, vUE recommends asynchronous requests during the Created (beforeCreated data is not mounted) lifecycle. React componentWillMount () {constructor (); / / Call setState (); So let’s start with that.
- There are two reasons why asynchronous requests are not recommended for constructor: 1. 2. SetState is meaningless here.
- ComponentWillMount will be deprecated at 16.x, so it is not recommended
- Asynchronous requests are made in this lifecycle because this lifecycle calls setState to render
It makes sense to make asynchronous requests in componentDidMount.
How is the virtual DOM converted to the real DOM in component mount?
Before the React component is mounted, the React component is a JavaScript object known as a virtual DOM. React creates its own virtual DOM in the form of a binary tree representing the entire UI structure. It saves the virtual DOM tree to memory. Structure is as follows
// React component HTML <div class="demo"> <p class="item"> UI Components </p> </div>Copy the code
// An object to store the key/value pair class: 'demo' }, children:[ {tagName:"p",props:{class:"item"}} ] }Copy the code
Virtual DOM vs direct manipulation of the real DOM?
In the normal front-end page, if the whole page data changes, it is reasonable for us to reset the whole HTML, but if only a fast data changes on the page, then we reset the whole page at this time will waste performance. For the virtual DOM, you just need to update the relevant data on the object and re-render all parts of the page. The comparison is as follows:
- Native DOM: Render HTML string + recreate all DOM elements
- Virtual DOM: Render Virtual DOM + diff + necessary DOM updates
DOM updates
When we use setState or the parent component’s props to change, the component’s lifecycle is as follows:
componentWillReceiveProps(The method is out of date and will not be described too much)- ShouldComponentUpdate: Parameters nextProps (props to be updated), nextState (state to be updated)
Note: If the return value is false, componentDidUpdate() is not called.
shouldComponentUpdate(nextProps,nextState){
console.log('----should update---')
return false
}
componentDidUpdate(){
console.log('-----did update------')
}
Copy the code
-
ComponentWillUpdate (method is out of date, not to mention too much)
-
ComponentDidUpdate: The hook function is triggered when a component is updated. For example, setState or props changes to the parent element.
-
render
1. Perform setState multiple times in react and render only once 2. Method is the only method that must be implemented in a class component. 3. When called, returns one of the following types: React element array or fragments string or numeric type (rendered as text nodes) Boolean or NULL (not rendered) 4. ShouldComponentUpdate () returns false, then render() is not called 5. Each call returns the same value without modifying component state and does not interact with the browser.Copy the code
Why can’t REACT directly change state?
Using this.state directly can change the value of state but does not trigger component updates. This can cause two problems: the content of the component page and the state of the component are inconsistent. Therefore, we need to call setState method to update the status.
Why doesn’t assigning state directly work?
From the previous question we know that setState performs steps, how can we directly assign a value to the state instead of putting the state into the state? Therefore, react updates will not be triggered.
Is setState synchronous or asynchronous?
- SetState is “asynchronous” only in synthesized events and hook functions, and synchronous in both native events and setTimeout.
- The setState code itself is synchronized. Because the react synthesis event and hook function are called before the update sequence, it is impossible to get the updated values in the synthesis event and hook function immediately
Component Update Principle
In the loading of components in React, the update operation is an inevitable operation of components. In the above content, we have had a general understanding of the implementation steps of setState. This section focuses on how React implements its complex component update during the update process.
Why might setState trigger component updates be an asynchronous pair?
Execution steps:
- Call this.setState({demo:”demo”}) in the function.
- The new state in setState is stored in the pending queue
- Check whether the status needs to be updated in batches
- If yes, all new states are stored in pending before updating.
- If not, start updating the new status
The react call to setState triggers a component update:
- SetState is mounted on the component prototype chain,
ReactComponent.prototype.setState = function (partialState, callback) { ! (typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? "development" ! == 'production' ? invariant(false, 'setState(...) : takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0; this.updater.enqueueSetState(this, partialState); if (callback) { this.updater.enqueueCallback(this, callback, 'setState'); }};Copy the code
- EnqueueSetState is called when setState is executed
When is setState synchronized?
When we use React encapsulated events, we enter a transaction, which does not directly trigger the Batch Update. However, when we use the native event mechanism (such as addEventListener), due to the lack of React encapsulation, setState will directly trigger batch Update to synchronize the update state.
The DOM is destroyed
- ComponentWillUnmount: Life cycle triggered when a component is destroyed.
In the React lifecycle componentWillUnmount although we rarely use it here, it can be useful in situations such as terminating a timer when leaving a component or unbinding a global event.
conclusion
Based on the summary above, I have a deeper understanding of react component loading. The process can be roughly divided into three stages: mount, update, and uninstall. When loading the React component, I think we need to pay attention to the following points: how the virtual Dom is rendered into the real Dom during mount and what setState does during update.