React's understanding of setState synchronization or asynchrony

1. setState synchronization? Asynchronous?

In the class component of React, we can use the setState method to update the state. But sometimes you can't get the latest data after using setState.

In fact, the execution process and code of setState in React are synchronized, which is only caused by the performance optimization mechanism of React framework itself. The calling sequence of synthetic events and lifecycle functions in React is before updating, so the updated values cannot be obtained immediately in synthetic events and lifecycle functions, forming an asynchronous form.

If the setState method is called repeatedly n times in a composite event, if React is not optimized, the current component will be rendered n times, which is a great waste of performance. Therefore, React combines multiple calls to the setState method into one for performance reasons. When setState is executed, the data in the state will not be updated immediately.

As mentioned earlier, calling setState directly in the synthetic event and lifecycle function of React will show an asynchronous form.

In addition, if you go beyond the performance optimization mechanism of React and use setState in native events and settimeouts, it will show the form of synchronization.

2. Asynchronous

1. React synthesis event

Events directly used in React, such as onChange and onClick, are encapsulated by React. They are synthetic events and managed by React. Then, due to the performance optimization mechanism, calling setState directly in the composite event will show an asynchronous form.

In the following code, in the synthesis event onClick, directly add 1 to the count in state, and then print the value of count. As a result, when you click the button for the first time, 0 will be printed instead of the latest 1.

state = { count: 0 };
add = () => {
    this.setState({ count: this.state.count + 1 });
    console.log(this.state.count); // 0
};
render() {
    return (
        <>
            <div>Current count:{this.state.count}</div>
            <button onClick={this.add}>add</button>
        </>
    );
}

2. Life cycle function

The lifecycle function is also managed by React. Calling setState directly in the lifecycle function will also show an asynchronous form.

In the following code, in the life cycle componentDidMount function, add 1 to the count in state, and then print the value of count. The result is 0 instead of the latest 1.

state = { count: 0 };
componentDidMount() {
    this.setState({ count: this.state.count + 1 });
    console.log(this.state.count); // 0
}
render() {
    return (
        <>
            <div>Current count:{this.state.count}</div>
            <button>add</button>
        </>
    );
}

3. Performance is synchronous

1. Native events

The process executed by setState itself is synchronous. Using native events and bypassing the management of React will show the form of synchronization.

The following code obtains the DOM element through the id and binds the click event with the native method. In the click event, add 1 to the count in state, and then print the count value. The latest count value of 1 will be printed.

state = { count: 0 };
componentDidMount() {
    const btn = document.getElementById('btn');
    btn.onclick = () => {
        this.setState({ count: this.state.count + 1 });
        console.log(this.state.count); // 1
    };
}
render() {
    return (
        <>
            <div>Current count:{this.state.count}</div>
            <button id="btn">add</button>
        </>
    );
}

2. setTimeout

In the following code, a timer setTimeout is written in the life cycle componentDidMount function. In setTimeout, the count in state is added by 1, and then the count value is printed. The latest count value of 1 will be printed.

Although setState is also written in the life cycle componentDidMount function, it is not written directly in componentDidMount, but sets a layer of setTimeout. In this way, setState takes the form of synchronization.

state = { count: 0 };
componentDidMount() {
    setTimeout(() => {
        this.setState({ count: this.state.count + 1 });
        console.log(this.state.count); // 1
    }, 0);
}
render() {
    return (
        <>
            <div>Current count:{this.state.count}</div>
            <button>add</button>
        </>
    );
}

4. The second parameter of setstate

Whether setState is written in object or function, it has the second parameter, which is an optional callback function. This callback function is called only after the state is updated and the interface is updated (after render is called).

As shown in the following code, although setState is invoked directly in componentDidMount, it prints the value of count in the callback function of setState, gets the latest value of 1, because the callback function is called after the update of the state, and of course, it gets the latest count.

state = { count: 0 };
componentDidMount() {
    this.setState({ count: this.state.count + 1 }, () => {
        console.log(this.state.count); // 1
    });
}
render() {
    return (
        <>
            <div>Current count:{this.state.count}</div>
            <button>add</button>
        </>
    );
}

📘📘 Welcome to my blog:
https://lzxjack.top/

Keywords: Javascript React Optimize

Added by newman on Tue, 09 Nov 2021 11:42:31 +0200