Introduction to the
React has made some incremental changes to the lifecycle hook function since v16.3. Some lifecycle hook functions have been deprecated and some have been added.
- Comparison of old and new lifecycle functions
- Why should the old hook function be discarded
- Explain the new lifecycle usage scenarios
- Example code is demonstrated and summarized
Comparison of old and new life cycles
A complete React component lifecycle calls the following hooks in sequence:
old lifecycle
mount
- constructor
- componentWillMount
- render
- componentDidMount
update
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
uninstall
- componentWillUnmount
new lifecycle
- mount
- constructor
- getDerivedStateFromProps
- render
- componentDidMount
- update
- getDerivedStateFromProps
- shouldComponentUpdate
- render
- getSnapshotBeforeUpdate
- componentDidUpdate
- uninstall
- componentWillUnmount
From the above the life cycle of contrast, we see not hard, the React since v16.3 abandoned componentWillMount componentWillReceiveProps componentWillUpdate three hooks
Analysis of abandonment causes
It took Facebook more than two years to get React Fiber out of the way, because in v15 updates were synchronous and one main thread was often tied up for long periods of time, causing page performance issues
React Fiber uses the browser requestIdleCallback to fragment interruptible tasks, with each piece running for a short time so that a single thread is not monopoled
For more information, please click the following link: Morgan Zhihu
How does React Fiber affect the life cycle?
The React Fiber Reconciliation process may pause and continue, so the lifecycle hooks before mounting and updating may not execute or execute multiple times;
React currently provides aliases for these lifecycle hooks:
- UNSAFE_componentWillMount
- UNSAFE_componentWillReceiveProps
- UNSAFE_componentWillUpdate
Act17 will only provide aliases, with individual names designed to disgust you from using them.
Explain the new life cycle
Life cycle function of each phase
constructor()
Constructor () is called before the React component is mounted. When implementing the constructor for the react.componentsubclass, super() should be called before any other statement.
Super inherits this object from the parent class to subclasses (MDN reference)
In general, the React constructor is only used in two cases:
- To initialize the internal state of the function
- Bind the instance to the event handler function
If state is not initialized or method binding is not performed, nothing needs to be written constructor() and just set this.state
You cannot call this.setstate () inside the constructor() function because the first render() has not yet been executed, which means the DOM node has not yet been mounted
static getDerivedStateFromProps(nextProps, prevState)
GetDerivedStateFromProps () is called before the Render method is called, and is called during initialization and subsequent updates
Return value: An object is returned to update state. If null is returned, nothing is updated
Parameters: The first parameter is props to be updated, and the second parameter is state of the previous state. You can compare props and state to add some restrictions to prevent useless state updates
Note: getDerivedStateFromProps is a static function. You can’t use this, which means you can only do things that have no side effects
As for why? Please move on to Big Morgan. – Zhihu
render()
The render() method is the only one that must be implemented in the class component to render the DOM, and the Render () method must return the reactDOM
Note: do not setState in render, otherwise it will trigger an infinite loop and crash memory
componentDidMount()
ComponentDidMount () is called immediately after the component is mounted. ComponentDidMount () is a good time to send a network request, enable event listening methods, and call setState() directly from the hook function.
shouldComponentUpdate(nextProps, nextState)
ShouldComponentUpdate () is called before component update and controls whether or not the component is updated. Return true if the component is updated and false if the component is not updated
Contains two parameters. The first parameter is the props value to be updated, and the second parameter is the state value to be updated. You can compare the props or state value before and after the update and add some restrictions to determine whether to update and optimize performance
Deep comparisons or using json.stringify () in shouldComponentUpdate() are not recommended. This is very inefficient and can hurt performance
Do not call setState() in shouldComponentUpdate as this will cause an infinite loop of updates and renders until the browser memory crashes
Use the built-in PureComponent component instead
getSnapshotBeforeUpdate(prevProps, prevState)
GetSnapshotBeforeUpdate () is called before the last render output is committed. That is, after render, when the component is about to be mounted.
It allows the component to capture some information (such as scroll position) before the DOM is actually updated, and any values returned by this lifecycle are passed as arguments to componentDidUpdate(). If no value needs to be passed, return NULL
componentDidUpdate(prevProps, prevState, snapshot)
ComponentDidUpdate () is called immediately after the update. The first render will not be executed
Contains three parameters, the first of which is the previous props value. The second is the last state value. The third is the “snapshot” parameter passing if the component implements the getSnapshotBeforeUpdate() life cycle (not often)
SetState () can be used to compare the props before and after conditional statements, otherwise it will cause an infinite loop
componentWillUnmount()
ComponentWillUnmount () is called when a component is about to be unmounted or destroyed.
This life cycle is a good time to cancel network requests, remove listening events, clean up DOM elements, clean up timers, and so on
Life cycle execution order
When creating
- constructor()
- static getDerivedStateFromProps()
- render()
- componentDidMount()
update
- static getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
When unloading
- componentWillUnmount()
Examples show
The react version of the following code is 16.4.0, which changes the parent component props. The parent component unloads and remounts the child component, and the child component changes its state. The execution sequence of its lifecycle is explained
Component code presentation
Parent component: parent-js
import React, { Component } from 'react';
import { Button } from 'antd';
import Child from './child';
const parentStyle = {
padding: 40.margin: 20.backgroundColor: 'LightCyan'};const NAME = 'Parent component: ';
export default class Parent extends Component {
constructor() {
super(a);console.log(NAME, 'constructor');
this.state = {
count: 0.mountChild: true}; }static getDerivedStateFromProps(nextProps, prevState) {
console.log(NAME, 'getDerivedStateFromProps');
return null;
}
componentDidMount() {
console.log(NAME, 'componentDidMount');
}
shouldComponentUpdate(nextProps, nextState) {
console.log(NAME, 'shouldComponentUpdate');
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log(NAME, 'getSnapshotBeforeUpdate');
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log(NAME, 'componentDidUpdate');
}
componentWillUnmount() {
console.log(NAME, 'componentWillUnmount');
}
/** * Modifies the method passed to the child component property count */
changeNum = () = > {
let { count } = this.state;
this.setState({
count: ++count,
});
};
/** * Toggle the methods of mounting and unmounting child components */
toggleMountChild = () = > {
const { mountChild } = this.state;
this.setState({
mountChild: !mountChild,
});
};
render() {
console.log(NAME, 'render');
const { count, mountChild } = this.state;
return (
<div style={parentStyle}>
<div>
<h3>The parent component</h3>
<Button onClick={this.changeNum}>Change the attribute count passed to the child component</Button>
<br />
<br />
<Button onClick={this.toggleMountChild}>Unmount/mount child components</Button>
</div>
{mountChild ? <Child count={count} /> : null}
</div>); }}Copy the code
Child component: child.js
import React, { Component } from 'react';
import { Button } from 'antd';
const childStyle = {
padding: 20.margin: 20.backgroundColor: 'LightSkyBlue'};const NAME = 'Child component: ';
export default class Child extends Component {
constructor() {
super(a);console.log(NAME, 'constructor');
this.state = {
counter: 0}; }static getDerivedStateFromProps(nextProps, prevState) {
console.log(NAME, 'getDerivedStateFromProps');
return null;
}
componentDidMount() {
console.log(NAME, 'componentDidMount');
}
shouldComponentUpdate(nextProps, nextState) {
console.log(NAME, 'shouldComponentUpdate');
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log(NAME, 'getSnapshotBeforeUpdate');
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log(NAME, 'componentDidUpdate');
}
componentWillUnmount() {
console.log(NAME, 'componentWillUnmount');
}
changeCounter = () = > {
let { counter } = this.state;
this.setState({
counter: ++counter,
});
};
render() {
console.log(NAME, 'render');
const { count } = this.props;
const { counter } = this.state;
return (
<div style={childStyle}>
<h3>Child components</h3>
<p>Count: {count}</p>
<p>Subcomponent state counter: {counter}</p>
<Button onClick={this.changeCounter}>Change its state counter</Button>
</div>); }}Copy the code
The interface display
Explore the execution order of the lifecycle in terms of when five component states change
Initialize the parent and child components
When the parent component is first rendered to load:
The printing order of the console is:
- Parent component: constructor()
- Parent component: getDerivedStateFromProps()
- Parent component: render()
- Child component: constructor()
- Child component: getDerivedStateFromProps()
- Child component: render()
- Child component: componentDidMount()
- Parent component: componentDidMount()
The child component modifies its state state
Click the button of subcomponent [change its own state counter], its value of [own state counter] will be +1, and the printing order of the console is as follows:
-
Child component: getDerivedStateFromProps()
-
Child component: shouldComponentUpdate()
-
Child component: render()
-
Child component: getSnapshotBeforeUpdate()
-
Child component: componentDidUpdate()
Modify the props passed to the child component in the parent component
Click the [change the attribute count passed to the child component] button in the parent component, then the value of [attribute count passed from the parent component] on the interface will be + 1, and the printing order of the console is as follows:
-
Parent component: getDerivedStateFromProps()
-
Parent component: shouldComponentUpdate()
-
Parent component: render()
-
Child component: getDerivedStateFromProps()
-
Child component: shouldComponentUpdate()
-
Child component: render()
-
Child component: getSnapshotBeforeUpdate()
-
Parent component: getSnapshotBeforeUpdate()
-
Child component: componentDidUpdate()
-
Parent component: componentDidUpdate()
Uninstall subcomponents
Click the [Uninstall/Mount child component] button in the parent component, the child component will disappear on the interface, and the printing sequence of the console is as follows:
-
Parent component: getDerivedStateFromProps()
-
Parent component: shouldComponentUpdate()
-
Parent component: render()
-
Parent component: getSnapshotBeforeUpdate()
-
Child component: componentWillUnmount()
-
Parent component: componentDidUpdate()
5. Remount child components
Click the [Uninstall/Mount child component] button in the parent component again, then the child component will be rendered again on the interface, and the printing order of the console is as follows:
-
Parent component: getDerivedStateFromProps()
-
Parent component: shouldComponentUpdate()
-
Parent component: render()
-
Child component: constructor()
-
Child component: getDerivedStateFromProps()
-
Child component: render()
-
Parent component: getSnapshotBeforeUpdate()
-
Child component: componentDidMount()
-
Parent component: componentDidUpdate()
Summary of parent-child component lifecycle execution order:
-
When the state of the child component changes, the parent component does not update, that is, it does not trigger the life cycle of the parent component
-
When the state of the parent component changes (including mounting and unmounting of the child component), it triggers its own lifecycle and updates of the child component
render
As well asrender
Before the life cycle, the parent component executes firstrender
As well asrender
In subsequent declaration cycles, the child component executes first and alternates with the parent component
When a child component is unmounted, only its own componentWillUnmount life cycle is executed and no other life cycle is triggered
This is my knowledge points according to their own summary, if there is insufficient, you can leave a message for me to correct. Finally, I hope you can give me more thumbs up + attention, your recognition is my motivation to move forward!
The sample code
If you need to test, please click the code location