I am trying to make a tic tac toe game using reactjs. I have a function named setSquareValue
to set the value of squares to X
but when I am clicking on a square all the other squares also filling with X
.
The hierarchy is Game.js -> Board.js -> Square.js
. I am using useState()
which is in Game.js
and also the function setSquareValue
is in Game.js
. I am passign the function to Square.js
through Board.js
.
Here is my codes:
Game.js
import React, { useState } from 'react';
import './Game.css'
import Board from './Board';
const Game = () => {
const [value, setValue] = useState(null);
const setSquareValue = () => {
setValue("X")
}
return (
<div className='game'>
<h1 style={{color: "#fff"}}>Tic Tac Toe</h1>
<h4 style={{color: "#2D033B"}}>Winner: </h4>
<Board value={value} setSquareValue={setSquareValue} />
</div>
);
};
export default Game;
Board.js
import React from "react";
import Square from "./Square";
import "./Board.css";
const Board = ({ value, setSquareValue }) => {
const squareKeys = [1, 2, 3, 4, 5, 6, 7, 8, 9];
return (
<div className="board">
{squareKeys.map(squareKey => (
<Square
key={squareKey}
value={value}
setSquareValue={setSquareValue} />
))}
</div>
);
};
export default Board;
Square.js
import React from "react";
import "./Square.css";
const Square = ({ value, setSquareValue }) => {
return (
<div className="square" onClick={() => setSquareValue()}>
{value}
</div>
);
};
export default Square;
I want, when I click a certain square, only that square fill with X
. But every square is filling with X
. How can I solve this?
I tried but X
is appearing in every box of the game.
Edited: Added CSS codes
Game.css
.game {
background-color: #AD7BE9;
width: 100%;
height: 100vh;
padding: 2rem;
display: flex;
flex-direction: column;
align-items: center;
}
Board.css
.board {
background-color: #645CBB;
color: #fff;
padding: 1rem;
margin-top: 1rem;
border-radius: 5px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
Square.css
.square {
border: 1px solid #fff;
height: 5rem;
width: 5rem;
font-size: 20px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
4
Answers
You are passing the value to every single square in your map function, for the solution you can move your
value
state andsetSquareValue
function to square component so that every square itself has its own value.updated Square.js:
also you don’t need to pass
value
andsetSquareValue
from Game.js to Board.js and Square.js anymore;The problem is where you are tracking
value
. Move the logic to store thevalue
state fromGame.js
toSquare.js
When your app begins, there is one instance of
Game
which has an initial value set tovalue
. Then you pass this single value toBoard
, where it renders that same value 9 times. Likewise, when you change that single value, it gets changed inGame
, then passed toBoard
, then finally rendered 9 times.Let
Square
store its own state.You are creating a unique state for all of the square in
Game
component. so if you change any time all of the square state will change so this problem occurs. So what you can do is instead of common state, you can create an individual state inSquare
component as:CODESANDBOX LINK
It is because you are using only one state variable for all square:
const [value, setValue] = useState(null);
You can declare as array variable that length is 9 for 9 square.
Game.js
Board.js
Square.js