0

Please help me, I really dont get it when the value of this.state.isX printed console is always true. Why setState not work in this case. Here is my source code?`

class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
      isX: true
    };
  }
  handle(){
    this.setState({value: 'X',isX:!this.state.isX});
    console.log(this.state.isX)
  }
  render() {
    return (
      <button className="square" onClick={() =>{this.handle()}}>
        {this.state.value}
      </button>
    );
  }
}
Kraylog
  • 7,383
  • 1
  • 24
  • 35

2 Answers2

1

It's because setState is asynchronous. Think of it as of Promise:

handle(){
  new Promise((resolve) => {
    setTimeout(() => {
      resolve("success")
    }, 1000)
  }).then(result => {
    console.log(result);
  })
  console.log('this will be printed before "success"')
}

You know that a code declared after the Promise, will execute immediately. The same is with setState.

If you want to be sure code executes after the state was updated use callback function:

handle(){
  this.setState({value: 'X',isX:!this.state.isX}, () => {
    console.log(this.state.isX)
  });
}

Links:

Why setState isn't synchronous.

Tomasz Mularczyk
  • 34,501
  • 19
  • 112
  • 166
0

setState is asynchronous; you can't immediately read back the value set. If you just wait a tick with a timer or something before logging, you'll see everything is fine. At least, I think so.

Reference: setState() does not always immediately update the component. It may batch or defer the update until later.

Also, minor performance nit: don't use arrow functions in render() to bind; instead, always define the handler itself as an arrow function.

Ed Staub
  • 15,480
  • 3
  • 61
  • 91