You might think setState is a function that executes synchronously. You can’t have asynchrony. But there are cases where setState does execute asynchronously. First, a brief introduction to the use of setState:

setState(res1[,res2]);
Copy the code

SetState takes two arguments, the first of which can be an object or a function

The first contestant is the objectthis.setState({
    n: 1} the first argument is the functionthis.setState((state) = > {
    return {
        n: 1}})Copy the code

The functional way to write it is to return the object as the return value, but the important thing is its argument, and the argument to this function is actually the current state.

class DeepSwtState extends Component {
    state = {
        n: 1
    }
    handleClick = () = > {
        this.setState(cur= > {
            console.log('Writing the function of the first parameter', cur); {n: 1}}
            return {
                n: cur.n + 1.a: 1}})}render() {
        return (
            <>
                <span>{this.state.n}</span>
                <button onClick={this.handleClick}>+</button>
            </>); }}Copy the code

So the second argument to setState: the second argument is an optional function, but the argument to this function has no meaning. What matters is the processing of the result of the first argument, as explained below.

Here’s a quick look at the asynchrony of setState.

class DeepSwtState extends Component {
    state = {
        n: 1
    }
    handleClick = () = > {
        this.setState({
            n: this.state.n + 1
        })
        console.log(The value of 'n ':.this.state.n); // Print the value of 'n: '1
    }
    render() {
        console.log('Render executes'); / / after the output
        return (
            <>
                <span>{this.state.n}</span>
                <button onClick={this.handleClick}>+</button>
            </>); }}Copy the code

As you can see from the above code output, it is the value of n first, n value is 1. But didn’t you change the value of n using setState? Why the output of n is still 1. React setState is asynchronous when the render function is executed first after the click event, and the value of n is directly output.

Render first, then output n, using the second parameter of setState.

Next we provide a method that operates with the second function of setState.

class DeepSwtState extends Component {
    state = {
        n: 1
    }
    handleClick = () = > {
        this.setState({
            n: this.state.n + 1
        }, () = > {
            console.log(The value of 'n 'in the callback function output:'.this.state.n); // The third execution has an output value of 2
        })
        console.log(The value of 'n ':.this.state.n);// The output value of the first execution is 1
    }
    render() {
        console.log('Render executes'); // The second execution
        return (
            <>
                <span>{this.state.n}</span>
                <button onClick={this.handleClick}>+</button>
            </>); }}Copy the code

But what if there are multiple setStates on the page that change the state value? What should the output look like?

this.setState({
    n: this.state.n + 1
})
console.log(The value of 'n ':.this.state.n); // Output: 1
this.setState({
    n: this.state.n + 1
})
console.log(The value of 'n ':.this.state.n); // Output: 1
this.setState({
    n: this.state.n + 1
})
console.log(The value of 'n ':.this.state.n); // Output: 1
Copy the code

If there are more than one setState in an HTML event, the output will be 1 and the page display will increment by 1 due to the asynchronous execution mechanism.

The output is only incremented by 1. SetState = this.setState = this.setState = this.setState = this.setState = this.setState = this.setState = this.setState = this.setState = this.setState = this.setState = this.setState = this.setState = this.setState And so on and so on and so on and so on.

So far I have two solutions to this situation. If you have a better solution, please comment below.

The first argument is an object, the second object is a function, and the second argument is this.setState, and then the data processing.

class DeepSwtState extends Component {
    state = {
        n: 1
    }
    handleClick = () = > {
         this.setState({
             n: this.state.n + 1
         }, () = > {
             this.setState({
                 n: this.state.n + 1
             }, () = > {
                 this.setState({
                     n: this.state.n + 1})})})}render() {
        console.log('Render executes'); 
        return (
            <>
                <span>{this.state.n}</span>
                <button onClick={this.handleClick}>+</button>
            </>); }}Copy the code

So you can see that clicking the button to add 3, but this is really uncomfortable to write, nested scalp tingling.

So here comes the second approach: the second approach is to use the setState argument as described above, where the first argument is a function.

this.setState(cur= > {
    return {
        n: cur.n + 1}})this.setState(cur= > ({ n: cur.n + 1}))
this.setState(cur= > ({ n: cur.n + 1}))
Copy the code

This way it looks friendly and comfortable, and clicking the button adds 3 directly.

But how many times has the render function been called in this case? When is it executed after the second argument? Is it going to be executed after the setState is executed as before or is it going to be executed after all the set states are executed?

Let me explain them one by one:

First of all, if the state is changed many times, then the render will be changed many times, in fact, the render will only be executed once, you can try to see if I am correct.

Second, when the second argument is executed. The second argument is not executed until all setState has been executed.

class DeepSwtState extends Component {
    state = {
        n: 1
    }
    handleClick = () = > {
        this.setState(cur= > {
            return {
                n: cur.n + 1.a: 1}},() = > {
            console.log(this.state); {n: 4, a: 1, b: 2, c: 3}
            console.log('The first asynchronous setState execution is complete with the value n:'.this.state.n); // The first asynchronous setState execution is complete with n: 4
        })
        this.setState(cur= > ({ 
            n: cur.n + 1.b: 2
        }))
        this.setState(cur= > ({ 
            n: cur.n + 1.c:3}}))render() {
        console.log('Render executes');
        return (
            <>
                <span>{this.state.n}</span>
                <button onClick={this.handleClick}>+</button>
            </>); }}Copy the code

The output of this.state and this.state.n is the result of all setState execution, so it is not difficult to see that when there are many setstates, the second parameter will be executed after all setState execution.

Follow me and bring you a blog post once a week that benefits you.