Reputation: 497
I am having issue with resetting the game whenever I click on reset button.
I have created tic tac toe game with react hooks with 2 components Game and Box.How can I add reset button with the use of React hooks.
I am Trying to make a with the code below.Also I tried to add reset button in it but is not working as required.Please help me out on how I can use reset button correctly to reset the box to empty.
Here is my Box component.
import React, { useState } from 'react'
import './style.css'
function Box(props) {
const [text, setText] = useState('')
function toggleText() {
if(text === '') {
setText(props.currentState)
props.changeTurn(props.row, props.col)
}
}
return <div className="box" onClick={toggleText}>{text}</div>
}
export default Box
Here is my Game Component.
import './style.css'
import Box from '../Box'
const board = [[],[],[]]
function Game() {
const [turn, setTurn] = useState('X')
const [winningtext, setWinningText] = useState('')
console.log(board)
function changeTurn(row, col) {
board[row][col] = turn
setTurn(turn => turn === 'X' ? 'O' : 'X' )
//console.log(board.length)
const winner = checkForWin()
//console.log(winner)
if(winner) {
setWinningText(winner + ' Won!')
}
}
// Winning game logic
function checkForWin() {
// row test
for(let i = 0; i < board.length; i++) {
const row = board[i]
//console.log(row[0])
if(row[0] === row[1] && row[1] === row[2] && row[0]){
return row[0]
}
}
//column test
for(let i = 0; i < board.length; i++) {
const el1 = board[0][i]
const el2 = board[1][i]
const el3 = board[2][i]
//console.log(`${el1} ${el2} ${el3}`)
if(el1 === el2 && el2 === el3 && el1) {
return el1
}
}
//diagonal test
const d1 = board[0][0]
const d2 = board[1][1]
const d3 = board[2][2]
if(d1 === d2 && d2 === d3 && d1) {
return d1
}
const p1 = board[0][2]
const p2 = board[1][1]
const p3 = board[2][0]
if(p1 === p2 && p2 === p3 && p1) {
return p1
}
return false
}
function reset() {
//Clear all grids and winner message
setWinningText('')
}
return <div className="game">
<h1>Tic Tac Toe</h1><br/>
<button className="reset" onClick={reset}>Reset</button><br/><br/>
<div id="winning-text">{winningtext}</div>
<div className="row row-1">
<Box row={0} col={0} currentState={turn} changeTurn={changeTurn} />
<Box row={0} col={1} currentState={turn} changeTurn={changeTurn} />
<Box row={0} col={2} currentState={turn} changeTurn={changeTurn} />
</div>
<div className="row row-2">
<Box row={1} col={0} currentState={turn} changeTurn={changeTurn} />
<Box row={1} col={1} currentState={turn} changeTurn={changeTurn} />
<Box row={1} col={2} currentState={turn} changeTurn={changeTurn} />
</div>
<div className="row row-3">
<Box row={2} col={0} currentState={turn} changeTurn={changeTurn} />
<Box row={2} col={1} currentState={turn} changeTurn={changeTurn} />
<Box row={2} col={2} currentState={turn} changeTurn={changeTurn} />
</div>
</div>
}
export default Game
Upvotes: 1
Views: 1639
Reputation: 5650
boards
) you want that to be within a React component. You could reset boards
by setting it to the same initial value (eg: [[], [], []]
) but it will not re-render because React won't know it changed. The suggestion I offered below is to move boards
to use the useState
hook so whenever it changes React can properly re-render.board
and the local value in the Box
component were storing similar state so it would be a challenge to keep them in sync. Rather, having a single board
value in the parent and passing a callback to the Box
will probably make your life easier and avoid weird data synchronization issues.grid
for this (seems like a perfect use case).map
for each row and column to reduce the need for the duplication (this is simple enough it's not a big deal, but with this, you could easily make it a 5 x 5 grid or something).function Box(props) {
const { value, changeTurn, row, col } = props;
function toggleText() {
if (!value) {
changeTurn(row, col);
}
}
return (
<div className="box" onClick={toggleText}>
{value}
</div>
);
}
function Game() {
const [board, setBoard] = React.useState([[], [], []]);
const [turn, setTurn] = React.useState("X");
const [winningtext, setWinningText] = React.useState("");
console.log(board);
function changeTurn(row, col) {
const newBoard = [...board];
const newRow = [...board[row]];
newBoard[row] = newRow;
newBoard[row][col] = turn;
setBoard(newBoard);
setTurn(turn => (turn === "X" ? "O" : "X"));
//console.log(board.length)
const winner = checkForWin();
//console.log(winner)
if (winner) {
setWinningText(winner + " Won!");
}
}
// Winning game logic
function checkForWin() {
// row test
for (let i = 0; i < board.length; i++) {
const row = board[i];
//console.log(row[0])
if (row[0] === row[1] && row[1] === row[2] && row[0]) {
return row[0];
}
}
//column test
for (let i = 0; i < board.length; i++) {
const el1 = board[0][i];
const el2 = board[1][i];
const el3 = board[2][i];
//console.log(`${el1} ${el2} ${el3}`)
if (el1 === el2 && el2 === el3 && el1) {
return el1;
}
}
//diagonal test
const d1 = board[0][0];
const d2 = board[1][1];
const d3 = board[2][2];
if (d1 === d2 && d2 === d3 && d1) {
return d1;
}
const p1 = board[0][2];
const p2 = board[1][1];
const p3 = board[2][0];
if (p1 === p2 && p2 === p3 && p1) {
return p1;
}
return false;
}
function reset() {
setBoard([[], [], []]);
setWinningText("");
}
return (
<div className="game">
<h1>Tic Tac Toe</h1>
<br />
<button className="reset" onClick={reset}>
Reset
</button>
<br />
<br />
<div id="winning-text">{winningtext}</div>
<div className="boxes">
{[0, 1, 2].map(row => {
return [0, 1, 2].map(col => {
return (
<Box
row={row}
col={col}
key={`${row}-${col}`}
value={board[row][col]}
currentState={turn}
changeTurn={changeTurn}
/>
);
});
})}
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Game />, rootElement);
.boxes {
display: grid;
grid-template-columns: 32px 32px 32px;
}
.box {
border: 1px solid red;
width: 32px;
height: 32px;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Upvotes: 1
Reputation: 1652
You could make the box component stateless, so you move the state logic from each box component out of it into the game component instead. You already have an array for the whole board, so why not just pass the state from the board to each box instead? Then you can also reset the board array, which would reset all boxes.
Check the following example. This hasn't been tested, but think it would work.
import React from 'react'
import './style.css'
function Box(props) {
function onClick() {
props.changeTurn(props.row, props.col)
}
return <div className="box" onClick={onClick}>{props.currentState}</div>
}
export default Box
import './style.css'
import Box from '../Box'
const board = [[],[],[]];
function Game() {
const [turn, setTurn] = useState('X')
const [winningtext, setWinningText] = useState('')
console.log(board)
function changeTurn(row, col) {
board[row][col] = turn
setTurn(turn => turn === 'X' ? 'O' : 'X' )
//console.log(board.length)
const winner = checkForWin()
//console.log(winner)
if(winner) {
setWinningText(winner + ' Won!')
}
}
// Winning game logic
function checkForWin() {
// row test
for(let i = 0; i < board.length; i++) {
const row = board[i]
//console.log(row[0])
if(row[0] === row[1] && row[1] === row[2] && row[0]){
return row[0]
}
}
//column test
for(let i = 0; i < board.length; i++) {
const el1 = board[0][i]
const el2 = board[1][i]
const el3 = board[2][i]
//console.log(`${el1} ${el2} ${el3}`)
if(el1 === el2 && el2 === el3 && el1) {
return el1
}
}
//diagonal test
const d1 = board[0][0]
const d2 = board[1][1]
const d3 = board[2][2]
if(d1 === d2 && d2 === d3 && d1) {
return d1
}
const p1 = board[0][2]
const p2 = board[1][1]
const p3 = board[2][0]
if(p1 === p2 && p2 === p3 && p1) {
return p1
}
return false
}
function reset() {
//Clear all grids and winner message
const board = [[],[],[]];
}
return <div className="game">
<h1>Tic Tac Toe</h1><br/>
<button className="reset" onClick={reset}>Reset</button><br/><br/>
<div id="winning-text">{winningtext}</div>
<div className="row row-1">
<Box row={0} col={0} currentState={board[0][0]} changeTurn={changeTurn} />
<Box row={0} col={1} currentState={board[0][1]} changeTurn={changeTurn} />
<Box row={0} col={2} currentState={board[0][2]} changeTurn={changeTurn} />
</div>
<div className="row row-2">
<Box row={1} col={0} currentState={board[1][0]} changeTurn={changeTurn} />
<Box row={1} col={1} currentState={board[1][1]} changeTurn={changeTurn} />
<Box row={1} col={2} currentState={board[1][2]} changeTurn={changeTurn} />
</div>
<div className="row row-3">
<Box row={2} col={0} currentState={board[2][0]} changeTurn={changeTurn} />
<Box row={2} col={1} currentState={board[2][1]} changeTurn={changeTurn} />
<Box row={2} col={2} currentState={board[2][2]} changeTurn={changeTurn} />
</div>
</div>
}
export default Game
Upvotes: 1