Reputation: 2724
I'm trying to build a simple react tic tac toe app, and I've gotten fairly far but now I'm getting an error I've been unable to debug.
I have a feeling it has to do with how my renderPlaySquare(i)
method is set up, but after that I'm lost ...
It is that the playSquareStates
state is not being set up correctly?
Sorry for the long post and thank you for your help.
I've included all of my code here because it's not very long, as well as the error.
Here are the two errors
Board.renderPlaySquare src/App.js:53
50 |
51 | renderPlaySquare(i) {
52 | debugger;
> 53 | return (
54 | <PlaySquare value={this.props.playSquareStates[i]} onClick={() => this.props.onClick(i)}
55 | />
56 | );
View compiled Board.render src/App.js:66
63 | <div>
64 | {/* Sets the index of the board*/}
65 | <div className="board-row">
> 66 | {this.renderPlaySquare(0)}
67 | {this.renderPlaySquare(1)}
68 | {this.renderPlaySquare(2)}
69 | </div>
And here is my main project
import React, {Component} from 'react';
// import ReactDOM from 'react-dom'
import './index.css'
// Functions for the game
function PlaySquare(props) {
debugger;
return (
<button
className="playSquare"
onClick={props.onClick}>
{props.value}
</button>
);
}
// Declare a winner
function whoIsTheWinner(combination) {
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],
];
// Loop through combinations
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (combination[a] && combination[a] === combination[b] && combination[a] === combination[c]) {
return combination[a];
}
}
return null;
}
// Main classes for the game
// The main component of the game, where the
// squares live
class Board extends Component {
renderPlaySquare(i) {
debugger;
return (
<PlaySquare value={this.props.playSquareStates[i]} onClick={() => this.props.onClick(i)}
/>
);
}
render() {
// Create the buttons they are going to play on
return (
<div>
{/* Sets the index of the board*/}
<div className="board-row">
{this.renderPlaySquare(0)}
{this.renderPlaySquare(1)}
{this.renderPlaySquare(2)}
</div>
<div className="board-row">
{this.renderPlaySquare(3)}
{this.renderPlaySquare(4)}
{this.renderPlaySquare(5)}
</div>
<div className="board-row">
{this.renderPlaySquare(6)}
{this.renderPlaySquare(7)}
{this.renderPlaySquare(8)}
</div>
</div>
);
}
}
class Game extends Component {
constructor(props) {
super(props);
this.state = {
history: [{
playSquareStates: Array(9).fill(null)
}],
xIsNext: true
};
}
handleClick(i) {
const historyAll = this.state.history;
const currentGame = historyAll[historyAll.length - 1];
const currentGameConfiguration = currentGame.playSquareStates.slice();
if (whoIsTheWinner(currentGameConfiguration) || currentGameConfiguration[i]) {
return;
}
currentGameConfiguration[i] = this.state.xIsNext ? 'X' : 'O';
// Now set the state AND history
this.setState({
history: historyAll.concat([{
playSquareStates: currentGameConfiguration
}]),
xIsNext: !this.state.xIsNext,
});
}
render() {
const historyAll = this.state.history;
const currentGame = historyAll[historyAll.length - 1];
const winner = whoIsTheWinner(currentGame.playSquareStates);
let currentTurn;
if (winner) {
currentTurn = 'Winner: ' + winner;
} else {
currentTurn = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
}
return (
<div className="game">
<div className="game-board">
<Board
playSquares = {currentGame.playSquareStates}
onClick = {(i) => this.handleClick(i)}
/>
</div>
<div className="game-info">
<div>
{currentTurn}
</div>
<ol>
{/* TODO */}
</ol>
</div>
</div>
);
}
}
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<h1>Welcome to React my Tic Tac Toe App</h1>
</header>
<Game/>
</div>
);
}
}
export default App;
Upvotes: 0
Views: 685
Reputation: 22323
In your Game
component, you render your Board
component like so:
<Board
playSquares = {currentGame.playSquareStates}
onClick = {(i) => this.handleClick(i)}
/>
This creates a prop
on the Board
component of playSquares
, not playSquareStates
.
Therefore, you should use:
<PlaySquare value={this.props.playSquares[i]} onClick={() => this.props.onClick(i)}
Upvotes: 2