0
votes

This is the code of tic tac toe taken from https://reactjs.org/ where my aim is to select particular square components. This code has a game, board and a square component. The square component is rendered 9 times in board method.And the entire board is rendered in the game component So is there a way wherein i can specifically highlight/style a particular square component.

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





class Board extends React.Component {

 renderSquare(i)


{
return (
  <Square

    value={this.props.squares[i]}
    onClick={() => this.props.onClick(i)}

  />
);


 }

this render function is creating 9 squares (3X3 grid)

 render() 
{


return (
  <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 {


constructor(props) {
super(props);
this.state = {
  history: [{ squares: Array(9).fill(null), }],
  xIsNext: true,
  count:0,


   };
  }






  reset()




{
    const history = this.state.history;
    const curr= history[history.length -1];
    console.log(curr);
    const a =curr.squares.fill(null);
    this.setState({history: history.concat([{
        squares: a,
      }])});     
    this.state.count=0;
     }









 handleClick(i)


{


const history = this.state.history;
const current= history[history.length -1];
const squares = current.squares.slice();

if(calculateWinner(squares) || squares[i] )
{

  return;



 }



 this.setState({count:this.state.count+1});


squares[i] = this.state.xIsNext ? 'X' : 'O';
this.setState({history: history.concat([{
    squares: squares,
  }]),
     xIsNext: !this.state.xIsNext,
              });




}



  render() {
const history =  this.state.history;
const current= history[history.length-1];
const winner=calculateWinner(current.squares);

let status;
if(winner)
  {
  status= 'winner: '+ winner;

  }if(!winner)
    {

    status = 'Next player:'  + (this.state.xIsNext ? 'X' : 'O') ;
    }
if(!winner && this.state.count==9)
  {
    status ="game tied";
  }


return (
  <div className="game">
    <div className="game-board">
      <Board 
        squares={current.squares}
        onClick={(i) => this.handleClick(i)}
        />
    </div>
    <div className="game-info">
      <div>{status  }</div>
      <ol><button onClick={() => this.reset() }>{/* TODO */"reset" }</button></ol>
    </div>
  </div>
);


 }
}





ReactDOM.render(


 <Game />,
  document.getElementById('root')
);

this function contains Winning logic how can i style a particular square component

function calculateWinner(squares) {



const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],];



 for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
  return squares[a];
}
  }

      return null;
}

the CSS file

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;
}
2
Hi Hussain. Style the square when? When it's clicked?Andy
Hi Andy. My aim is to style the squares when either 'X' or 'O' wins(3 in a row, col. or diagonal squares)..Hussain

2 Answers

1
votes

If you want to style if the square click you must save which square is clicked so you should save the index of the square in the state so :

class Board extends React.Component {

 renderSquare(i)


{
return (
  <Square
    selectedSquareIndex={this.state.squareSelected} {/* here we pass square index*/}
    value={this.props.squares[i]}
    onClick={() => this.props.onClick(i)}

  />
);


 }

and then in Square :

function Square(props) {
      return (
        <button  className={["square",
         'selectedSquare':props.value === props.selectedSquareIndex //if true we add style 
     ]} onClick={props.onClick} >
          {props.value}
        </button>
      );
    }

in CSS

.selectedSquare{background-color:red;}

but how to set state is when this happen in square :

onClick={() => this.props.onClick(i)

track it in onClick.

Update 1 first if you create a Code Sandbox for me I can more help to you. ok first I describe the algorithm.We know that this.props.onClick(i) pass the index of the square that is clicked. also, we want to style the square that is clicked so first we must store the index of the square that is clicked.we store it in parent of Square maybe Board or maybe Game component. so Image in the square is clicked then we store index in state.so we have index of square that is clicked.then we pass this number to square with selectedSquareIndex so square can know which square is clicked and check this number with index of self and if these number are equal mean this square is clicked and we add it a classname.

Updatae 2

Here you can see what I done to add color to square with click: Code Sandbox but you can change the specifixIndex in app.js for hit or other thing you wan.t

0
votes

You can style a specific square using CSS's ':nth-of-type()' method. For example in your case, if you wanted to make only the first square red you would do the following:

.square:nth-of-type(1) {
  background-color: red;
}