Understanding of the synchronous or asynchronous problem of setState in React

Understanding of the synchronous or asynchronous problem of setState in React

1. Is setState synchronous? asynchronous?

In React's class components, we can use the setState method to update the state. But sometimes after using setState, the latest data cannot be obtained.

In fact, the execution process of setState itself in React is synchronized with the code, which is only caused by the performance optimization mechanism of the React framework itself. In React, synthetic events and lifecycle functions are called before updates, which results in the failure to immediately obtain updated values ​​in synthetic events and lifecycle functions, thus forming an asynchronous form.

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

As mentioned earlier, calling setState directly in React's synthetic events and lifecycle functions will behave asynchronously.

In addition, if you bypass React's performance optimization mechanism and use setState in native events or setTimeout, it will behave synchronously.

2. Behaves as asynchronously

1. React Synthetic Events

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

In the following code, in the synthetic event onClick, the count in the state is directly increased by 1, and the value of count is printed afterwards. 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. Lifecycle functions

The lifecycle function is also managed by React. Calling setState directly in the lifecycle function will also behave asynchronously.

In the following code, in the lifecycle componentDidMount function, the count in the state is increased by 1, and the value of count is printed afterwards. 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. Appears as synchronization

1. Native events

The execution process of setState itself is synchronous. Using native events and bypassing React's management will show a synchronous form.

The following code obtains the DOM element by id and binds the click event using native methods. In the click event, add 1 to the count in the state, and then print the value of count. As a result, the latest count value 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

The following code writes a timer setTimeout in the life cycle componentDidMount function. Inside setTimeout, the count in the state is increased by 1, and the value of count is printed afterwards. As a result, the latest count value 1 will be printed.

Although setState is also written in the componentDidMount function of the life cycle, it is not written directly in componentDidMount, but is wrapped with a layer of setTimeout. In this way, setState behaves synchronously.

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

Regardless of whether setState is written in object-oriented or functional-oriented form, 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 1 is obtained. Because the callback function is called after the state is updated, 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>
        </>
    );
}

This is the end of this article about understanding the synchronous or asynchronous problem of setState in React. For more relevant content about setState synchronous or asynchronous in React, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Code analysis of synchronous and asynchronous setState issues in React
  • The use of setState in React and the use of synchronous and asynchronous
  • Use of setState synchronous and asynchronous scenarios in React

<<:  Detailed explanation of MySQL three-value logic and NULL

>>:  About the "occupational disease" of designers

Recommend

A performance bug about MySQL partition tables

Table of contents 2. Stack analysis using pt-pmap...

Detailed process of upgrading glibc dynamic library in centos 6.9

glibc is the libc library released by gnu, that i...

Summary of MySQL password modification methods

Methods for changing passwords before MySQL 5.7: ...

Simple Mysql backup BAT script sharing under Windows

Preface This article introduces a simple BAT scri...

Implementation of MySQL select in subquery optimization

The following demonstration is based on MySQL ver...

Alibaba Cloud Server Ubuntu Configuration Tutorial

Since Alibaba Cloud's import of custom Ubuntu...

Install redis and MySQL on CentOS

1|0MySQL (MariaDB) 1|11. Description MariaDB data...

The connection between JavaScript and TypeScript

Table of contents 1. What is JavaScript? 2. What ...

js simple and crude publish and subscribe sample code

What is Publish/Subscribe? Let me give you an exa...

Solution to the Multiple primary key defined error in MySQL

There are two ways to create a primary key: creat...

js regular expression lookahead and lookbehind and non-capturing grouping

Table of contents Combining lookahead and lookbeh...

Solution to the conflict between Linux kernel and SVN versions

Phenomenon The system could compile the Linux sys...

View the frequently used SQL statements in MySQL (detailed explanation)

#mysql -uroot -p Enter password mysql> show fu...