简体   繁体   中英

Why does using an arrow function give the updated version of the state in React in comparison to calling the function normally?

Take the following react code

class Foo extends React.Component {
    constructor(props) {
        super(props);
        this.state = {state1: true, state2: false, state3: "hello"}
        this.onClick = this.onClick.bind(this)

    }

    onClick() {
        this.setState({state1: false, state2: true, state3: "goodbye"}, console.log(this.state))
    }

    render() {
        return(
            <button onClick = {this.onClick}></button>
        )
    }
}

ReactDOM.render(<Foo />, document.getElementById('root'));

When I use console.log in the callback for setState , I have to click the button twice in React in order for the console to display the correct version of state.

However, if write this.setState({state1: false, state2: true, state3: "goodbye"}, () => console.log(this.state)) instead, adding an arrow function, clicking the button once outputs the correct version of the state in the console. Why is that? Why does an arrow function output different behaviour in this scenario?

The expression console.log(this.state) is first evaluated, and the resulting value is passed into setState .

In other words, this

this.setState({state1: false, state2: true, state3: "goodbye"}, console.log(this.state))

can be re-written to the following without changing its behavior:

let consoleLogResult = console.log(this.state)
this.setState({state1: false, state2: true, state3: "goodbye"}, consoleLogResult)

You log the current state before you set it.

Now, console.log always returns undefined , so consoleLogResult above will always be undefined . It behaves like you never passed a callback 'function' at all.


If you instead pass () => console.log(this.state) , it evaluates to a function, which is called by React after the state transition was executed.

Because the second one argument for this.setState() is callback that is called when state is updated. console.log() doesn't return function, it's called at the same time when you call this.setState()

In your first example, you're doing this:

this.setState({state1: false, state2: true, state3: "goodbye"}, console.log(this.state))

That is not passing a function as the second parameter, it is evaluating the function console.log with the current value of this.state and passing its returned result (which for console.log is always undefined) as the second parameter. But if you use the second parameter of setState , React expects it to be a function, not undefined, so it won't actually have any callback to run when the state updates.

In your second example, you are actually passing a new function as the parameter, and once that function is called (as a callback, by React, when the new state has been set), that function calls console.log ; by then, the state is set and so it logs the new value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM