Reputation: 308
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;
}
Upvotes: 0
Views: 4054
Reputation:
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;
}
Upvotes: 0
Reputation: 7919
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
Upvotes: 1