Julia
Julia

Reputation: 13

Setstate not working propertly in ReactJS

I am relative new to ReactJS and I have some problems with setState.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import './index.js';

class Square extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        value: null,
        xNextPlayer: true
      };
    }

    render() {
      return (
        <button
          className="square"
          onClick={ async () => {
              console.log(this.state.xNextPlayer);
              if(this.state.xNextPlayer === true) {
                this.setState({value: 'X'});
              } else {
                this.setState({value: 'O'});
              }
              await this.setState({xNextPlayer: !this.state.xNextPlayer});
              console.log(this.state.xNextPlayer);
          }}
        >
          {this.state.value}
        </button>
      );
    }
  }

  class Board extends React.Component {
    renderSquare(i) {
      return <Square />;
    }

    render() {
      const status = 'Next player: X';

      return (
        <div>
          <div className="status">{status}</div>
          <div className="board-row">
            {this.renderSquare(0)}
            {this.renderSquare(1)}
            {this.renderSquare(2)}
          </div>
          <div className="board-row">
            {this.renderSquare(3)}
            {this.renderSquare(4)}
            {this.renderSquare(5)}
          </div>
          <div className="board-row">
            {this.renderSquare(6)}
            {this.renderSquare(7)}
            {this.renderSquare(8)}
          </div>
        </div>
      );
    }
  }

  class Game extends React.Component {
    render() {
      return (
        <div className="game">
          <div className="game-board">
            <Board />
          </div>
          <div className="game-info">
            <div>{/* status */}</div>
            <ol>{/* TODO */}</ol>
          </div>
        </div>
      );
    }
  }

  // ========================================

  ReactDOM.render(
    <Game />,
    document.getElementById('root')
  );
  **strong text**

The problem now is that xNextPlayer is not updated correctly. When I first click, xNextPlayer is true as it should. Then I want to set it to false. It does this correctly and console logs false. But when I click again, it is again set back to true. The first console log then is true, the second false.

But I want to store the value and be false.

Has anybody a solution?

Upvotes: 0

Views: 59

Answers (3)

Shahnad S
Shahnad S

Reputation: 1167

use this method.i think it will be works.

const handleClick =(xNextPlayerStatus:boolean)=>{

    if(xNextPlayerStatus){
     this.setState({value: 'X'})
    }
    else if(!xNextPlayerStatus){
    this.setState({value: 'O'})

    }}     



        <button className="square" onClick={()=>handleClick(this.state.xNextPlayer)}>

Upvotes: 0

Łukasz Karczewski
Łukasz Karczewski

Reputation: 1218

Look at this sandbox: https://codesandbox.io/s/cool-paper-z8kpu . I copypasted your code (except I changed the initial value of a box to "U") and everything works as expected, and that is:

  1. I click on a box with "U" - FIRST logs true and SECOND logs false
  2. I click on another box with "U" - the same thing happens
  3. I click on a box with "X" - FIRST logs false and SECOND logs true
  4. I click on a box with "O" - FIRST logs true and SECOND logs false

You need to remember that each box has its own state, the fact that they are all the same component does not mean that they have a shared state.

Upvotes: 2

Sense
Sense

Reputation: 1106

Firstly, using async/await on the setState is not a good idea because setState doesn't return a promise. You have to use the 2nd parameter of the setState function, which is the callback function (as a Promise), if you want to wait for the new state before updating your xNextPlayer value.

If you want to check your new xNextPlayer after updating it in your setState, get it back from the console.log in the callback scope.

this.setState({ xNextPlayer: !this.state.xNextPlayer }, () => { console.log(this.state.xNextPlayer) })`

Upvotes: 0

Related Questions