2

I am trying to set up a conditional statement that basically takes a button and says when I click on the button I want an X to appear and I want the button's color to change to red currently the whole board is changing to the color I'm asking it to.

I've tried putting the condition in different places to see if that would work it doesn't work where does the conditional statement need to be

    if (this.state.xIsNext = 'X') {
    backgroundColor='red';
    }
else if (this.state.xIsNext = 'O') {
    backgroundColor='yellow';
     }
  }
  renderSquare(i, backgroundColor) {

return (
  <Square
    value={this.state.squares[i] || 'X'}
    onClick={() => this.handleClick(i)}
  />
);
}
 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>
);
  }
}

the project can also be viewed herehttps://codepen.io/zachary-blumstein/pen/KKPJaLG?editors=0010

1 Answers1

1

You can change the background in the state to be an object holding the color of each square and update it on click :

var player = {score: 1, name: 'Jeff'};

var newPlayer = Object.assign({}, player, {score: 2});

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      backgroundColor: {
        1: 'gray',
        2: 'gray',
        3: 'gray',
        4: 'gray',
        5: 'gray',
        6: 'gray',
        7: 'gray',
        8: 'gray',
        9: 'gray',
      },
      squares: Array(9).fill(null),
      xIsNext: true,
    };
  }

  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = this.state.xIsNext ? 'X' : 'O'
   
      
    this.setState({
      backgroundColor: {
        ...this.state.backgroundColor,
        [i]: this.state.xIsNext ? 'yellow': 'red'
      },
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });

  }
  
  checkColorOfSquare= (xIsNext, backgroundColor) => {
    if (this.state.xIsNext = 'X') {
        backgroundColor='red';
        }
    else if (this.state.xIsNext = 'O') {
        backgroundColor='yellow';
         }
  }
  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i] || 'X'}
        color={this.state.backgroundColor[i]}
        onClick={() => this.handleClick(i)}
      />
    );
    }
 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>
    );
  }
}



function Square(props) {
  return (
    <button className="square" onClick={props.onClick} style={{ backgroundColor: props.color}}>
      {props.value}
    </button>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Board />, rootElement);
body {
  font: 14px "Century Gothic", Futura, sans-serif;
  margin: 20px;
}

ol, ul {
  padding-left: 30px;
}

.board-row:after {
  clear: both;
  content: "";
  display: table;
}

.status {
  margin-bottom: 10px;
}

.square {
  background: #fff;
  border: 1px solid #999;
  float: left;
  font-size: 24px;
  font-weight: bold;
  line-height: 34px;
  height: 34px;
  margin-right: -1px;
  margin-top: -1px;
  padding: 0;
  text-align: center;
  width: 34px;
}

.square:focus {
  outline: none;
}

.kbd-navigation .square:focus {
  background: #ddd;
}

.game {
  display: flex;
  flex-direction: row;
}

.game-info {
  margin-left: 20px;
}
<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>

Or better, have the <Square /> component have its own state holding its color and its own click handler.

var player = {score: 1, name: 'Jeff'};

var newPlayer = Object.assign({}, player, {score: 2});

class Board extends React.Component {
  constructor(props) {
    super(props);
    this.state = {     
      squares: Array(9).fill(null),
      xIsNext: true,
    };
  }

  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = this.state.xIsNext ? 'X' : 'O'   
      
    this.setState({     
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }
  
  checkColorOfSquare= (xIsNext, backgroundColor) => {
    if (this.state.xIsNext = 'X') {
        backgroundColor='red';
        }
    else if (this.state.xIsNext = 'O') {
        backgroundColor='yellow';
         }
  }
  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i] || 'X'}        
        onClick={() => this.handleClick(i)}
        xIsNext={this.state.xIsNext}
        ndx={i}
      />
    );
    }
 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 Square extends React.Component {
  state = {
    color: 'gray'
  }

  handleClick = e => {    
     this.setState({
       color: this.props.xIsNext ? 'yellow': 'red'
     });
    
    this.props.onClick(this.props.ndx);
  }
  
  render(){
    return (
      <button className="square" onClick={this.handleClick} style={{ backgroundColor: this.state.color}}>
        {this.props.value}
      </button>
    )
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<Board />, rootElement);
body {
  font: 14px "Century Gothic", Futura, sans-serif;
  margin: 20px;
}

ol, ul {
  padding-left: 30px;
}

.board-row:after {
  clear: both;
  content: "";
  display: table;
}

.status {
  margin-bottom: 10px;
}

.square {
  background: #fff;
  border: 1px solid #999;
  float: left;
  font-size: 24px;
  font-weight: bold;
  line-height: 34px;
  height: 34px;
  margin-right: -1px;
  margin-top: -1px;
  padding: 0;
  text-align: center;
  width: 34px;
}

.square:focus {
  outline: none;
}

.kbd-navigation .square:focus {
  background: #ddd;
}

.game {
  display: flex;
  flex-direction: row;
}

.game-info {
  margin-left: 20px;
}
<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>
Taki
  • 17,320
  • 4
  • 26
  • 47
  • So let me get this straight for any state that I want to create in terms of color I need to storing the all the initial states of that color and where they might be hosted within the component when they are initiated? – Zachary Blumstein Sep 23 '19 at 21:44
  • what were you doing when you added this.setState({ backgroundColor: { ...this.state.backgroundColor, [i]: this.state.xIsNext ? 'yellow': 'red' – Zachary Blumstein Sep 23 '19 at 21:46
  • @ZacharyBlumstein I updated the answer with an approach that i would recommend, and the line you just mentionned is to update the right key in the state ( without losing the other keys ) `[i]` will translate to the the value of `i`and become ` this.setState({ backgroundColor: { ...this.state.backgroundColor, 5: ...` , check : https://stackoverflow.com/questions/43040721/how-to-update-nested-state-properties-in-react – Taki Sep 23 '19 at 21:49
  • I like the first idea better. It makes more sense and according to react components should only do one thing and not multiple things – Zachary Blumstein Sep 23 '19 at 21:50
  • yes, in the first approach you're asking the parent component to take care of the 9 child components' states, with the second one, every `Square` component is responsible for its own state, up to you :) – Taki Sep 23 '19 at 21:52