Understanding of setState synchronization or asynchronism in React

  • 2021-12-05 05:12:09
  • OfStack

Directory 1. setState synchronization? Asynchronous? 2. Be asynchronous 1. React composite event
2. Life cycle function
3. Show synchronization 1. Native events
2. setTimeout
4. Parameter 2 of setState

1. setState synchronization? Asynchronous?

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

In fact, the process and code executed by setState in React are synchronized, only because of the performance optimization mechanism of React framework itself. In React, the calling order of composite events and life cycle functions is before updating, which leads to the fact that the updated values cannot be obtained immediately in composite events and life cycle functions, thus forming an asynchronous form.

If the setState method is called 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 is executed by merging setState methods that are called multiple times into one for performance reasons. When setState is executed, the data in state is not updated immediately.

As mentioned earlier, calling setState directly in the composite events and life cycle functions of React will take an asynchronous form.

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

2. Be asynchronous

1. React composite event

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

The following code, in the composite event onClick, directly adds 1 to count in state, and prints the value of count after that. As a result, when the button is clicked 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 life cycle function is also managed by React, and calling setState directly in the life cycle function will also show asynchronous form.

In the following code, in the lifecycle componentDidMount function, add 1 to count in state, and print the value of count after that, and the result prints 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. Show synchronization

1. Native events

The processes executed by setState itself are synchronized, and using native events, bypassing the management of React, will take the form of synchronization.

The following code obtains the DOM element through id and binds the click event with the native method. In a click event, add 1 to count in state, and print the value of count after that, resulting in the latest count value of 1.


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, count in state is added by 1 inside setTimeout, and the value of count is printed after that, and the latest count value of 1 is printed as a result.

Although setState is also written in the life cycle componentDidMount function, it is not directly written in componentDidMount, but is covered with one 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. Parameter 2 of setState

Whether setState is written in object or function, there is a 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 called directly in componentDidMount, the value of count is printed in the callback function of setState, and the latest value of 1 is obtained, because the callback function is called only after the status update is completed, and of course the latest count can be obtained.


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>
        </>
    );
}

Related articles: