React source code + note

The introduction

React provides us with some lifecycle hook functions that allow us to do things in the hook function during important phases of React execution. So what are the hook functions in the React lifecycle? Let’s summarize

Extraction life cycle

<! -- Prepare a "container" --><div id="test"></div><! React core library --><script type="text/javascript" src=".. /js/react.development.js"></script><! React-dom () {react-dom ();<script type="text/javascript" src=".. /js/react-dom.development.js"></script><! -- Introduce Babel to convert JSX to JS --><script type="text/javascript" src=".. /js/babel.min.js"></script>

<script type="text/babel">
// Create a component
// Lifecycle callback <=> lifecycle hook function <=> lifecycle hook function <=> lifecycle hook function
class Life extends React.Component{

        state = {opacity:1}

        death = () = >{
                // Uninstall the component
                ReactDOM.unmountComponentAtNode(document.getElementById('test'))}// The component hangs
        componentDidMount(){
        // Timers cannot be placed in render because state constancy causes render to call timers again
                console.log('componentDidMount');
                this.timer = setInterval(() = > {
                    // Get the original state
                    let {opacity} = this.state
                    //减小0.1
                    opacity -= 0.1
                    if(opacity <= 0) opacity = 1
                    // Set new transparency
                    this.setState({opacity})
                }, 200);
        }

        // The component will be unmounted
        componentWillUnmount(){
                // Clear the timer
                clearInterval(this.timer)
        }

        // After initial rendering and status update
        render(){
                console.log('render');
                return(
                    <div>
                        <h2 style={{opacity:this.state.opacity}}>What if you can't React?</h2>
                        <button onClick={this.death}>Don't live</button>
                    </div>)}}// Render component
    ReactDOM.render(<Life/>.document.getElementById('test'))
</script>
Copy the code

Life Cycle (old version)

  1. Initialization phase: triggered by reactdom.render () — initial render
  • constructor()
  • componentWillMount()
  • render()
  • ComponentDidMount () =====> Usually does some initialization in this hook. For example, start timers, send network requests, and subscribe messages
  1. Update phase: triggered by the component’s internal this.setsate () or parent’s Render
  • shouldComponentUpdate()
  • componentWillUpdate()
  • Render () =====> One that must be used
  • componentDidUpdate()
  1. Unload components: by ReactDOM unmountComponentAtNode triggered ()
  • ComponentWillUnmount () =====> Usually this hook does some finishing work, such as turning off timers and unsubscribing messages
<! -- Prepare a "container" --><div id="test"></div><! React core library --><script type="text/javascript" src=".. /js/react.development.js"></script><! React-dom () {react-dom ();<script type="text/javascript" src=".. /js/react-dom.development.js"></script><! -- Introduce Babel to convert JSX to JS --><script type="text/javascript" src=".. /js/babel.min.js"></script>

<script type="text/babel">

// Create a component
class Count extends React.Component {

        / / the constructor
        constructor(props) {
                console.log('Count---constructor');
                super(props)
                // Initialization state
                this.state = { count: 0}}// Add the 1 button callback
        add = () = > {
                // Get the original state
                const { count } = this.state
                // Update the status
                this.setState({ count: count + 1})}// Unload the callback of the component button
        death = () = > {
                ReactDOM.unmountComponentAtNode(document.getElementById('test'))}// Force the update button callback
        force = () = > {
                // Not controlled by valve, do not change data in any state
                this.forceUpdate()
        }

        // The hook to be mounted by the component
        componentWillMount() {
                console.log('Count---componentWillMount');
        }

        // The component has mounted the hook
        componentDidMount() {
                console.log('Count---componentDidMount');
        }

        // The hook that the component will unload
        componentWillUnmount() {
                console.log('Count---componentWillUnmount');
        }

        // Control component update "valve", return true meaning can update, return false meaning cannot update
        // If you do not write the react hook, the React base will automatically complete it for you and return true if you write what you wrote
        shouldComponentUpdate() {
                console.log('Count---shouldComponentUpdate');
                return true
        }

        // The hook that the component will update
        componentWillUpdate() {
                console.log('Count---componentWillUpdate');
        }

        // The component's updated hook
        componentDidUpdate() {
                console.log('Count---componentDidUpdate');
        }

        render() {
                console.log('Count---render');
                const { count } = this.state
                return (
                    <div>
                        <h2>The current sum is: {count}</h2>
                        <button onClick={this.add}>I + 1 point</button>
                        <button onClick={this.death}>Uninstall the component</button>
                        <button onClick={this.force}>Force updates without changing data in any state</button>
                    </div>)}}// Parent component A
class A extends React.Component {
        // Initialization state
        state = { carName: 'Mercedes' }

        changeCar = () = > {
                this.setState({ carName: 'rolling'})}render() {
                return (
                    <div>
                        <div>I'm component A</div>
                        <button onClick={this.changeCar}>To change</button>
                        <B carName={this.state.carName} />
                    </div>)}}// Subcomponent B
class B extends React.Component {
        // The component is going to receive the props hook, which is not called the first time it passes the props parameter
        componentWillReceiveProps(props) {
                console.log('B---componentWillReceiveProps', props);
        }

        // Control module updated "valve"
        shouldComponentUpdate() {
                console.log('B---shouldComponentUpdate');
                return true
        }
        // The hook that the component will update
        componentWillUpdate() {
                console.log('B---componentWillUpdate');
        }

        // The component's updated hook
        componentDidUpdate() {
                console.log('B---componentDidUpdate');
        }

        render() {
                console.log('B---render');
                return (
                        <div>I am component B, and the vehicle I receive is :{this.props. CarName}</div>)}}// Render component
ReactDOM.render(<Count />.document.getElementById('test'))
</script>
Copy the code

React lifecycle

The React lifecycle consists of three phases: initialization phase, update phase, and destruction phase

Initialization phase

1. The constructor is carried out

Constructor is performed only once when a component is initialized

Usually it’s used to do both of these things

  1. Initialize the inside of the functionstate
  2. Binding function
Constructor (props) {console.log(' enter the constructor '); Super (props) this.state = {count: 0}} Copy codeCopy the code

Instead of using the constructor property, we now use a class-plus arrow function approach to replace constructor

For example, we can initialize state like this

state = {
	count: 0
};
Copy the code

2. Static getDerivedStateFromProps implementation (new hook)

This is one of two new hooks in the React release, and is said to be rarely used.

GetDerivedStateFromProps is called both during initialization and update, and is called before the Render method, which returns an object to update the state

GetDerivedStateFromProps is a directly bound static method on the class that takes two arguments, props and state

Props is the value to be substituted for state, and state is the current value before it was substituted

Note: The value of state is dependent on the props passed in at any time and does not change

The following

static getDerivedStateFromProps(props) {
    return props
}
ReactDOM.render(<Count count="109"/>,document.querySelector('.test'))
Copy the code

The value of count doesn’t change. It’s always 109

2. ComponentWillMount implementation (soon to be scrapped)

Life Cycle componentWillMount will not be executed if getDerivedStateFromProps and getSnapshotBeforeUpdate are present.

This method is called only once at mount time, indicating that the component is about to be mounted, and before the Render method.

This method will be deprecated in React 18. The React async mechanism may cause bugs if abused

3. The render

The Render () method is a mandatory method in the component to render the DOM, but it doesn’t actually manipulate the DOM, it just returns what it needs.

The implementation of DOM rendering is reactdom.render ()

Note: Avoid using setState in render, otherwise it will loop forever

4. ComponentDidMount execution

Execution of componentDidMount means that the initial mount operation is almost complete, and it is used to do something after the component has been mounted

The mount completion refers to the component being inserted into the DOM tree

Initialization phase summary

Constructor -> getDerivedStateFromProps or componentWillMount -> Render -> componentDidMount

Update the stage

The process of the new life cycle is documented here

1. GetDerivedStateFromProps execution

Execute the life cycle getDerivedStateFromProps, and the value returned is used to merge the state to generate a new state.

2. ShouldComponentUpdat execution

ShouldComponentUpdate () is called before the component is updated. It returns a value to control whether the component is updated or not, allowing updates to return true and not updating otherwise

3. The render

In the function that controls updates, render is executed only if it returns true to get the latest React element

4. GetSnapshotBeforeUpdate execution

Called before the last render output is committed, that is, when it is about to be mounted

React is equivalent to a snapshot of taobao shopping, which preserves the product content before placing an order. React is equivalent to the status before updating

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

5. ComponentDidUpdate execution

Components are called immediately after they are updated, not the first rendering


To this update phase is over, in the React in the old version, there are two hooks functions related to the updated componentWillReceiveProps and componentWillUpdate is abandoned

I don’t know much about componentWillReceiveProps

ComponentWillUpdate is executed before Render to indicate that the component is about to be updated

Destruction of phase

ComponentWillUnmount perform

Called when a component is about to be uninstalled or destroyed.

conclusion

Initialize the

  • constructor()
  • static getDerivedStateFromProps()
  • render()
  • componentDidMount()

update

  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()

The destruction

  • componentWillUnmount()