Xiaofeng Xie
Xiaofeng Xie

Reputation: 185

How to render style for child component individually?

I was going through the react tutorial(tic tac toe game) on React.js website and I want to style the each square individually when a user clicks it.More specially, a square should turn red when it is player X's turn and turn blue when it is player O's turn. I have tried to use props and state to change the color. However, react changes all the squares instead of changing the color of a square individually.

Below is what I've tried so far.

import React from 'react';
import ReactDOM from 'react-dom';

function Square (props) {

  let style={
    backgroundColor:props.bgColor,
    background:'#fff',
    border: '1px solid #999',
    float: 'left',
    fontSize: '24px',
    fontWeight: 'bold',
    lineHeight: '34px',
    height: '34px',
    marginRight:'-1px',
    marginTop: '-1px',
    padding: 0,
    textAlign:'center',
    width: '34px' 

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

  }

  class Board extends React.Component {
    constructor() {
      super();

      this.state = {
        squares: Array(9).fill(null),
        xIsNext:true,
        color:'white'
      };
    }

    handleClick=(i)=>e=> {     
      const squares = this.state.squares.slice();

      if(calculateWinner(squares) ||squares[i]){
          return;
      }
      squares[i] = this.state.xIsNext?'X':'O';

      this.setState({squares: squares,
    xIsNext:!this.state.xIsNext});
    }

    renderSquare(i) {
      return (
        <Square
          value={this.state.squares[i]}
          onClick={ this.handleClick(i)}
          bgColor={this.state.xIsNext?'red':'blue'}
        />
      );
    }

    render() {
      const winner = calculateWinner(this.state.squares);
      let status;
      if(winner){
        status ="Winner: "+winner;
      }else{
        status = 'Next player: '+(this.state.xIsNext?'X':'O');
      }
      let boardStyle={        
              clear: 'both',
              content: "",
              display: 'table'        
          }
      return (

        <div>
          <div className="status">{status}</div>
          <div className="board-row" style={boardStyle}>
            {this.renderSquare(0)}
            {this.renderSquare(1)}
            {this.renderSquare(2)}
          </div>
          <div className="board-row" style={boardStyle}>
            {this.renderSquare(3)}
            {this.renderSquare(4)}
            {this.renderSquare(5)}
          </div>
          <div className="board-row" style={boardStyle}>
            {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')
  );

  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;

  }

Upvotes: 0

Views: 107

Answers (2)

MukulSharma
MukulSharma

Reputation: 221

You can do this in renderSquare as well:

<Square value={this.state.squares[i]}
        onClick={ this.handleClick(i)}
        bgColor={this.state.squares[i]=='X'?'red':'blue'}/>

Upvotes: 0

Jani Siivola
Jani Siivola

Reputation: 730

You can decide the background colour inside each square based on it's own value. If it's 'X' you mark it red, if it's 'O' you mark it blue.

let style={
    backgroundColor: {props.value === 'X' ? 'red' : 'blue'},

Upvotes: 1

Related Questions