0
import {useState, useEffect} from 'react';

export default function App() {
  const [boardHistory, setBoardHistory] = useState([Array(3).fill().map(() => Array(3).fill(0))]);
  const [count, setCount] = useState(0);
  const [shouldDeactivate, setShouldDeactivate] = useState(false);
  console.log("count is " + count);
  const board = boardHistory[count];
  function onClick(i, j) {
    if (board[i][j] === 1 || shouldDeactivate) {
      return;
    }
    const newBoard = [...board];
    newBoard[i][j] = 1;
    setBoardHistory([...boardHistory, newBoard]);
    const newCount = count + 1;
    setCount(newCount);
    if (newCount == 9) {
      setShouldDeactivate(true);
    }
  }

  function deactivateCells() {
    const timer = setInterval(() => {
      setCount(prev => {
          if (prev === 0) {
            clearInterval(timer);
            setShouldDeactivate(false);
          } else {
            prev--;
          }
  
          return prev;
        });
    }, 300);
  }
  useEffect(() => {
    if (shouldDeactivate) {
      deactivateCells();
    }
  }, [shouldDeactivate]);

  return <Board board={board} onClick={onClick} count={count}/>
}

function Board(props) {
  const {board, onClick, count} = props;
  return (
    <div>
      {board.map((row, rowIndex) => {
        return <div key={rowIndex}>{row.map((grid, colIndex) => <Grid key={colIndex} count={count} onClick={() => onClick(rowIndex, colIndex)} cell={board[rowIndex][colIndex]}/>)}</div>
      })}
    </div>
  )
}

function Grid(props) {
  // some specific implementation 
}

I was trying to change the state of the counter when timer gets called, this should also change the board because the count was a different index. But my board doesn't get re-rendered when the count state is changed.

I don't know why. Can anyone help? Thanks.

alexchin
  • 1
  • 1
  • You are mutating the state here: `newBoard[i][j] = 1;` Restructure your code so the state isn't mutated, possibly by deep cloning it first. When you mutate state, rendering often has unexpected results, such as being skipped entirely. – CertainPerformance Feb 05 '23 at 06:35
  • But I'm already cloning a copy first, const newBoard = [...board]; so I'm not directly mutating the original state – alexchin Feb 05 '23 at 07:01
  • That copies the array, but only the array - you aren't cloning any of the array items, so the array items are the same as in the original state, which you proceed to mutate with `newBoard[i][j] = 1;`. Always avoid mutating state in React. – CertainPerformance Feb 05 '23 at 14:39

0 Answers0