Reputation: 135
This is an adaptation of the React tutorial.
My intent is to use the selection of one or two players to migrate towards an automatic
selection of moves. At this stage for some reason the selection of squares is not being
captured in the call to handleMove(i)
with the this.setState({squares:this.state.squares, xIsNext: !this.state.xIsNext})
statement, as can be seen from the
two console.log calls in both the Button and Square components.
This is the technique employed in the tutorial so I am not sure why the squares array is not
updating. I read other postings and Facebook's discussion of immutability that states
the function (in this case the handleMove(i)
, correct?) must complete before the change to state
is reflected in the overall state. The calls to console.log in the other componets as well as the overall DOM
do not reflect the clicks on the squares.
Can anyone tell me why this is not working? Thank you.
On JSBin
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Tic Tac Toe</title>
<script src="https://unpkg.com/react@latest/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script>
<script src="https://unpkg.com/[email protected]/babel.min.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id='root'></div>
<script type='text/babel' >
function Square(props){
console.log(props.value);
return(
<button className="square" onClick={() => props.onClick()}>{props.value}</button>
);
}
class Board extends React.Component{
renderSquare(i){
console.log(this.props.squares);
return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />
}
render(){
return(
<div className="board">
<div className="row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
class Game extends React.Component{
constructor(props){
super(props);
this.state = {
onePlayerGame: true,
squares: Array(9).fill(null),
xIsNext: true
}
}
onePlayer(){
this.setState({onePlayerGame: true});
return(
document.getElementById('onePlayer').style.color = "yellow",
document.getElementById('twoPlayer').style.color = "black"
);
}
twoPlayer(){
this.setState({ onePlayerGame: false});
return(
document.getElementById('onePlayer').style.color= "black",
document.getElementById('twoPlayer').style.color= "yellow"
);
}
handleMove(i){
const squares = this.state.squares.slice();
squares[i] = this.state.xIsNext ? 'X':'O';
this.setState({
squares: this.state.squares,
xIsNext: !this.state.xIsNext
})
}
render(){
return(
<div id="main">
<div>
<button className="gameSelect" id="onePlayer" value={this.state.onePlayerGame} onClick={() => this.onePlayer()} >One Player</button>
<button className="gameSelect" id="twoPlayer"value={this.state.onePlayerGame} onClick={() => this.twoPlayer()} >Two Players</button>
</div>
<Board
squares={this.state.squares}
onClick={(i) => this.handleMove(i)} />
</div>
);
}
}
ReactDOM.render(
<Game />,
document.getElementById('root')
)
</script>
</body>
</html>
Upvotes: 0
Views: 62
Reputation: 28407
The selection is captured, but you are not saving the new value of squares
in the state
.
this
handleMove(i){
const squares = this.state.squares.slice();
squares[i] = this.state.xIsNext ? 'X':'O';
this.setState({
squares: this.state.squares, <----- You are not assigning the new value
xIsNext: !this.state.xIsNext
})
}
should be
handleMove(i){
const squares = this.state.squares.slice();
squares[i] = this.state.xIsNext ? 'X':'O';
this.setState({
squares: squares,
xIsNext: !this.state.xIsNext
})
}
Here is the proper jsbin
Upvotes: 1