Home > Enterprise >  React state updates...but I don't know why
React state updates...but I don't know why

Time:10-12

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.

  • Related