I'm making a tic - tac - toe game using React, and I am confused as to how my state is updating. I'm using hooks.
I have a state array which contains 9 objects, each with properties 'num' (from 0 to 8) and with an empty string for 'val'. When a square has been clicked, depending on who is active or not, I wanted the value of the square to have been update to "X" or "O".
For this I presumed that I would have had to use the spread operator and update my state with my newly updated array, but I'm not, I'm using square brackets to select the square I want, and assigning it a new value depending on the player.
I'm just wondering how, I don't understand how my state updates, you can see in my code where I've commented out the use of the spread operator upon realising that it seems unnecessary. The logic is in my clickHandler. Any explanation or resource would be really handy for me to understand this, Thanks. App.js
import React from 'react';
import { useState } from 'react'
import Square from './components/Square'
// possible winning rows
// switch between player 1 and 2
// reset button
const App = () => {
const [playerX, setPlayerX] = useState([])
const [playerO, setPlayerO] = useState([])
// false = playerX
const [activePlayer, setActivePlayer] = useState(false)
const [square, setSquare] = useState([
{ num: 0, val: '' },
{ num: 1, val: '' },
{ num: 2, val: '' },
{ num: 3, val: '' },
{ num: 4, val: '' },
{ num: 5, val: '' },
{ num: 6, val: '' },
{ num: 7, val: '' },
{ num: 8, val: '' }
])
const clickHandler = (squareItem) => {
// square clicked
// let newSquares = [...square]
const squareUpdate = square[squareItem.num]
// check active player
if(activePlayer) {
// push square num to player array
setPlayerO([...playerO, squareItem.num ])
// change square value
squareUpdate.val = "O"
// update state array with changed
// setSquare([...newSquares])
setActivePlayer(!activePlayer)
}else {
// add square num to player array
setPlayerX([...playerX, squareItem.num ])
// change square value
squareUpdate.val = "X"
// update state array with changed
// setSquare([...newSquares])
setActivePlayer(!activePlayer)
}
}
return (
<div id="game">
<h1>Tic - Tac - Toe</h1>
<div id="grid">
{square.map((squareItem, index) => {
return <Square
activePlayer={activePlayer}
squareItem={squareItem}
clickHandler={clickHandler}
/>
})}
</div>
</div>
)
}
export default App
Square.js
import React from 'react'
const Square = ({ squareItem, clickHandler }) => {
return (
<div
onClick={() => clickHandler(squareItem)}
className="square"
value={squareItem.value}>
{squareItem.num}
</div>
)
}
export default Square
CodePudding user response:
Square is any array and referenced by instance and not value.
Because you call another setState (setActivePlayer) react rerenders the component with the values of square
changed but its still the same object reference and therefore has the updated values.
If you remove the other setState calls and only set the object values it wont rerender.