“This is the 12th day of my participation in the Gwen Challenge in November. See details of the event: The Last Gwen Challenge 2021”.

1. Two setStates, how many times?

As shown in the code below, there is a count in state. The button is bound to a click event that executes setState twice, incrementing the value of count each time.

How many times does setState execute when the button is clicked? How many times will render() execute?

Answer: Both times.

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

As a general rule, the first time the button is clicked, since setState is executed twice and count is incremented by one each time, render() should execute twice and count should be 2. But React doesn’t work that way.

Put the above code into the browser to run:

Initially, the page displays count with a value of 0, and the console prints render, which React first renders. React performs only one setState and only one render() operation.

The reason is that React combines multiple setstates in the same event response function internally to reduce the number of setState calls, thus reducing the number of rendering times and improving performance.

This explains why the last count is 1, because React merges the two setstates and render() is executed only once.

2. Two setStates, which one is called?

However, the above code does not verify which setState is executed after the React merge. Change count to + 2 in the second setState, as shown below, and leave the rest of the code unchanged:

state = { count: 0 };
handleClick = () = > {
    this.setState({ count: this.state.count + 1 });
    this.setState({ count: this.state.count + 2 }); / / instead of + 2
};
render() {
    console.log(`render`);
    return (
        <>
            <div>Current count: {this.state.count}</div>
            <button onClick={this.handleClick}>add</button>
        </>
    );
}
Copy the code

Put it in the browser again:

It turns out that when the button is clicked, count ends up being 2, +2, and render() is executed only once. React merges multiple setStates. If a property with the same name appears, the property with the same name will overwrite the property with the same name. For a property of the same name, the property in the last setState is finally executed.

3. Two setStates in setTimeout?

What if you add a timer setTimeout to the click event function, and execute the setState operation twice in the timer? The following code, in the event handler, writes a timer setTimeout, and puts two setStates into setTimeout.

state = { count: 0 };
handleClick = () = > {
    setTimeout(() = > {
        this.setState({ count: this.state.count + 1 });
        this.setState({ count: this.state.count + 2 });
    }, 0);
};
render() {
    console.log(`render`);
    return (
        <>
            <div>Current count: {this.state.count}</div>
            <button onClick={this.handleClick}>add</button>
        </>
    );
}
Copy the code

Running results:

The result shows that when the button is clicked, count finally changes to 3, so both the +1 and +2 operations are performed, and render() is executed twice.

This is because direct calls to setState in React synthesis events and lifecycle functions are managed by the React performance tuning mechanism, which merges multiple setstates. However, the call of setState in the native event and setTimeout is not managed by React, so multiple setstates are not merged. After several setstates are written, several setstates will be called.

4. To summarize

Events directly used in React, such as onChange and onClick, are synthesized events encapsulated by React and managed by React.

React Has a performance optimization mechanism for compositing events and lifecycle functions. Multiple setStates are merged. If an attribute with the same name appears, the attribute with the same name overwrites the attribute with the same name.

If you override the performance optimization mechanism of React and use setState in native events and setTimeout, React will not manage the setState. After writing setState several times, you will call setState several times.

The above is my humble opinion of learning, if there is anything wrong, welcome to point out the exchange!