In version 17.0.1, React has modified the life cycle of components. The new life cycle and the old life cycle have not changed much. The new life cycle has added two new hook functions, and three hook functions are outdated.
1, Old life cycle
The life cycle of components can be divided into three stages: initialization stage, update stage and uninstall stage.
Initialization phase: trigger in sequence.
constructor() --->
componentWillMount() --->
render() --->
componentDidMount()
Update phase: there are three update methods. Different methods trigger functions down from different hook functions in turn.
(1) the first is the whole phase of the update phase, which is triggered by the parent component's re render.
Parent component render -- >
componentWillReceiveProps() --->
shouldComponentUpdate() --->
componentWillUpdate --->
render() --->
componentDidUpdate()
(2). The second method is triggered after modifying the state (execute setState()).
Execute setstate() --- >
shouldComponentUpdate() --->
componentWillUpdate --->
render() --->
componentDidUpdate()
(3). The third method is forced update. Execute forceUpdate().
Execute forceupdate() --- >
componentWillUpdate --->
render() --->
componentDidUpdate()
Unloading phase: by reactdom Unmountcomponentatnode() trigger
componentWillUnmount()
Initialization phase
<script type="text/babel"> // Create component class Sum extends React.Component{ constructor(props) { console.log('constructor') super(props) // Initialization status this.state = {count: 0} } // Add button add = () => { // Get original status const {count} =this.state // Update status this.setState({count: count+1}) } // Component will be mounted componentWillMount() { console.log('componentWillMount') } // Component mounting completed componentDidMount() { console.log('componentDidMount') } //Timing of render call: initialize rendering, after status update render() { console.log('render') const {count} = this.state return( <div> <h2>{count}</h2> <button onClick={this.add}>+1</button> </div> ) } } ReactDOM.render(<Sum />, document.getElementById('test')) </script>
In the initialization stage, the commonly used hook function is componentDidMount(). After the component is mounted, for example, there is a timing function after the page is displayed.
When the page is just mounted, the number on the page will increase by 1 every second, and the timer will be written to componentDidMount():
<script type="text/babel"> // Create component class Sum extends React.Component{ state = {count:0} unmount = () => { // Uninstall components ReactDOM.unmountComponentAtNode(document.getElementById('test')) } // After the component is mounted, it is called only once componentDidMount() { // Set a timer and increase it every second this.timer = setInterval(()=>{ let {count} = this.state count += 1 this.setState({count}) },1000); } // When the component is about to be uninstalled componentWillUnmount() { // Clear timer clearInterval(this.timer) } //Timing of render call: initialize rendering, after status update render() { return( <div> <h2>{this.state.count}</h2> <button onClick={this.unmount}>Uninstall components</button> </div> ) } } // Render component to page ReactDOM.render(<Sum/>, document.getElementById('test')) </script>
Update phase:
The first refers to the parent component. This method requires two components, a child component and a parent component.
First, create two components, component A and component B. the calculation results are carried out in component A, and then the calculated results are transmitted to component B. the transmission data is transmitted by props, and the calculation results are displayed in component B. Component a saves the results in the state state, and the update state must update render, so it constitutes the condition for the parent component to re render.
<script type="text/babel"> //A component class Acomponent extends React.Component{ state = {count: 0} add = () => { this.setState({count: this.state.count+1}) } render() { return( <div> <div>A assembly</div> <button onClick={this.add}>+1</button> <Bcomponent count={this.state.count}/> </div> ) } } //B assembly class Bcomponent extends React.Component{ componentWillReceiveProps() { console.log('componentWillReceiveProps') } // If the control component update is not written, there will be a default value of true // Write must have a return value shouldComponentUpdate() { console.log('shouldComponentUpdate') return true } // Component will be updated componentWillUpdate() { console.log('componentWillUpdate') } // Component update completed componentDidUpdate() { console.log('componentDidUpdate') } render() { console.log('render') return( <div>B assembly{this.props.count}</div> ) } } // Render component to page ReactDOM.render(<Acomponent />, document.getElementById('test')) </script>
Only the first update condition triggers the {componentWillReceiveProps() hook function.
shouldComponentUpdate() is a hook function that can control the update of components and return a Boolean value. If it returns true, it will continue to execute downward.
If the return is false, the component will not be updated and the subsequent hook function will not be executed.
If the hook function shouldComponentUpdate() is not written in the code, React will give a default value of true. If the hook function is written in the code, the return value must be written. If the return value is not written, an error will be reported.
The second method is to update the status, which reloads the components.
The following content is not much, so the code of modifying status update, forced update and uninstalling components is written in one code.
<script type="text/babel"> // Create component class Sum extends React.Component{ state = {count:0} // Callback of button add = () => { // Get original status const {count} =this.state // Update status this.setState({count: count+1}) } // Uninstall components unmount = () => { ReactDOM.unmountComponentAtNode(document.getElementById('test')) } // Forced update force = () => { this.forceUpdate(); } // Component will be uninstalled componentWillUnmount() { console.log('componentWillUnmount') } // If the control component update is not written, there will be a default value of true // Write must have a return value shouldComponentUpdate() { console.log('shouldComponentUpdate') return true } // Component will be updated componentWillUpdate() { console.log('componentWillUpdate') } // Component update completed componentDidUpdate() { console.log('componentDidUpdate') } //Timing of render call: initialize rendering, after status update render() { console.log('render') const {count} = this.state return( <div> <h2>{count}</h2> <button onClick={this.add}>+1</button> <button onClick={this.unmount}>Uninstall components</button> <button onClick={this.force}>Force update without changing status</button> </div> ) } } // Render component to page ReactDOM.render(<Sum />, document.getElementById('test')) </script>
The first + 1 button is the button to update the status and save the displayed number in the status. It will be triggered in turn
You can control whether to update components by controlling the return value of {shouldComponentUpdate().
The third method is to force the update of components by calling the forceUpdate() function.
Because it is a forced update, it must be updated, so it is not controlled through shouldComponentUpdate().
In the process of writing code, you can update the status without updating the components, and you can force the components to be updated without updating the status. You can choose according to your own needs.
Unloading phase
In the unloading phase, there is only one hook function, and the componentWillUnmount() component will be unloaded by react Unmountcomponentatnode() triggers the unloading of components.
Some finishing work will be done at this stage. For example, in the previous example of timer, clear the timer in this hook function during unloading, otherwise an error will be reported.
2, New life cycle
Before understanding the new life cycle, we need to know why React needs to modify the life cycle. The content in the official website is as follows:
The above three life cycle methods are often misunderstood and abused. The React team needs to realize asynchronous rendering. In asynchronous rendering, their potential misuse problems may be greater, and there may be bug s in future versions of React.
That is to say, the React team is paving the way for the update of the later React version in advance to solve the possible problems in advance.
Two new lifecycles are introduced, static getDerivedStateFromProps and getSnapshotBeforeUpdate
getDerivedStateFromProps() emphasizes that it is static, so static should be added in front of it.
<script type="text/babel"> // Create component class Count extends React.Component{ state = {count: 0 } // Callback of button add = () => { // Get original status const {count} =this.state // Update status this.setState({count: count+1}) } // Get a derived state from props // If the value of state depends on props at any time, you can use static getDerivedStateFromProps(props, state) { console.log('getDeriveStateFromProps', props, state) return null // return props } getSnapshotBeforeUpdate(prevProps, prevState) { console.log('getSnapshotBeforeUpdate', prevProps, prevState) return 'React' } // Component update completed componentDidUpdate(prevProps, prevState, snapshotValue) { console.log('componentDidUpdate', prevProps, prevState, snapshotValue) } //Timing of render call: initialize rendering, after status update render() { console.log('render') const {count} = this.state return( <div> <h2>{count}</h2> <button onClick={this.add}>+1</button> {/*<button onClick={this.death}>Uninstall components < / button > <button onClick={this.force}>Force update without changing the status < / button >*/} </div> ) } } ReactDOM.render(<Count count={2}/>, document.getElementById('test')) </script>
It can return an object to update the state, or null to represent the new props, without any state update. If you don't use this function, it will increase the complexity of using the de bug state function very little.
Another new life cycle is getSnapshotBeforeUpdate. The return value of this life cycle will be passed to componentDidUpdate. Com as the third parameter
Figure is the running result of the above code.
The above two lines are triggered during component initialization and the following four lines are triggered during component update. getDerivedStateFromProps can get the props and state values of the current component, which are always the current values, while getSnapshotBeforeUpdate takes the previous values, which are the values when the component has not been updated.
When the component is updated, it is the updated component, and the information in the component before the update is gone. The information of the previous component can be returned by getSnapshotBeforeUpdate and passed to componentDidUpdate, which can store the information of the previous component. Everything can be stored, for example, keep the scroll position, component size data, etc. It is very useful in some cases.
summary
Whether it's an old life cycle or a new life cycle, there are three commonly used hook functions
componentDidMount(), initialization work;
componentDidUpdate(), update work;
componentWillUnmount(), to finish the work.
These three hook functions have not changed in the old life cycle or the new life cycle.
3, Using lifecycle hook functions in functional components
Hook is React16 New features and syntax added in version 8.0. state,refs and other React features (life cycle hook function) can be used in function components.
Effect Hook
Effect Hook allows you to perform side-effect operations in function components (used to simulate life cycle hooks in class components).
import React from "react" import ReactDOM from "react-dom" function Component() { const [count, setCount] = React.useState(0) function add() { setCount((count)=>{return count+1}) } function unmount() { ReactDOM.unmountComponentAtNode(document.getElementById('root')) } //Equivalent to componentDidMount() // React.useEffect(()=>{ // console.log('initialization ') // }, [] / / nothing is added in parentheses. It is only called when the page is just mounted //Equivalent to componentDidUpdate() // React.useEffect(()=>{ // console.log('initialize and update ') // }, [count] / / add the status in parentheses and update it when the status changes //Equivalent to componentWillUnmount() React.useEffect(()=>{ console.log('initialization') return ()=>{ console.log('Uninstall components') } },[]) return ( <div> <h2>{count}</h2> <button onClick={add}>+1</button> <button onClick={unmount}>uninstall</button> </div> ) } export default Component
(1) Syntax and Description:
useEffect(() => {
/ / any operation with side effects can be performed here
return() = > {/ / execute before uninstalling the component
/ / do some finishing work here, such as clearing the timer / unsubscribing
}
}, [stateValue] / / if [] is specified, the callback function will only be executed after the first render()
(2) You can think of useEffect Hook as a combination of the following three functions
componentDidMount()
componentDidUpdate()
componentWillUnmount()