Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

state is immediately available when setState is called after await

When calling setState after awaiting for another function and logging the state to the console - the value is immediately available.

I know that setState is asynchronous and in all other cases, it wouldn't be available immediately after calling it (but would be available in the setState callback)

When used without await (expected)

// inital value state is 0
const response = fetchSomething()
this.setState({
  value: 5
})

console.log(this.state.value) // prints 0

Used with await

// inital value state is 0
const response = await fetchSomething()
this.setState({
  value: 5
})

console.log(this.state.value) // prints 5

What am I missing here?

like image 383
Lana Petkovic Avatar asked Apr 12 '19 12:04

Lana Petkovic


1 Answers

When you make a function async and you await some expression, the following statements will be run after the awaited promise has been resolved under the hood.

The documentation states that setState() does not always immediately update the component, and it usually doesn't, but in this case when you update the state after a promise has been resolved in an event handler the state is updated immediately.

Example

class App extends React.Component {
  state = {
    value: 0
  };

  asyncClick = () => {
    Promise.resolve().then(() => {
      this.setState({
        value: 5
      });

      console.log(this.state.value);
    });
  };

  syncClick = () => {
    this.setState({
      value: 5
    });

    console.log(this.state.value);
  };

  render() {
    return (
      <div>
        <div>{this.state.value}</div>
        <button onClick={this.asyncClick}>Async click</button>
        <button onClick={this.syncClick}>Sync click</button>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>
like image 144
Tholle Avatar answered Oct 01 '22 03:10

Tholle