'A problem that i am having making conway's game of life in react (nextjs). when i press the Random button while it is running, it starts flickering

Here is a the code for you to try. both button works fine while the game is paused or running very fast, but if i set the timeout above 100 or 200 ms and the game is in a running state, if i press the random button the game starts flickering.

const numrow = 20;
const numcol = 50;

const getBlankGrid = () => {
  return Array(numrow).fill(Array(numcol).fill(0));
};


export default function Home() {
  const [count, setCount] = useState(0);
  const [grid, setGrid] = useState(getBlankGrid());
  const [running, setRunning] = useState(false);


  setTimeout(() => {
    if (!running) return;
    let newgrid = produce(grid, (nextGenGrid) => {
      for (let i = 0; i < numrow; i++) {
        for (let j = 0; j < numcol; j++) {
          let aliveNeibours = 0;
          for (let ii = i - 1; ii <= i + 1; ii++) {
            for (let jj = j - 1; jj <= j + 1; jj++) {
              let newi = ii;
              let newj = jj;
              if (ii === i && jj === j) continue;
              if (newi < 0) newi = numrow - 1;
              if (newi >= numrow) newi = 0;
              if (newj < 0) newj = numcol - 1;
              if (newj >= numcol) newj = 0;
              if (grid[newi][newj] === 1) aliveNeibours += 1;
            }
          }

          if (grid[i][j] === 1) {
            if (aliveNeibours < 2) nextGenGrid[i][j] = 0;
          }
          if (grid[i][j] === 1) {
            if (aliveNeibours === 2 || aliveNeibours === 3) {
              nextGenGrid[i][j] = 1;
            }
          }
          if (grid[i][j] === 1) {
            if (aliveNeibours > 3) {
              nextGenGrid[i][j] = 0;
            }
          }
          if (grid[i][j] === 0) {
            if (aliveNeibours === 3) {
              nextGenGrid[i][j] = 1;
            }
          }
        }
      }
    });
    setGrid(newgrid);
  },100);

  const randomhandler = () => {
    setGrid((grid) =>
      produce(grid, (gridCopy) => {
        for (let i = 0; i < numrow; i++) {
          for (let j = 0; j < numcol; j++) {
            gridCopy[i][j] = Math.random() > 0.2 ? 0 : 1;
          }
        }
      })
    );
  };

  return (
    <div>
      <Head>
        <title>Next.js App - Homepage</title>
      </Head>

      <div className="flex gap-1 justify-start px-5 py-1">
        <button
          onClick={() => setRunning((r) => !running)}
          className="p-1 rounded-full px-5 border-2 shadow-md hover:scale-105 transition-all bg-lime-400"
        >
          {running ? "Pause" : "Play"}
        </button>
        <button
          onClick={randomhandler}
          className="p-1 rounded-full px-5 border-2 shadow-md hover:scale-105 transition-all text-white bg-gray-400"
        >
          Random
        </button>
      </div>

      <div className={`p-5 grid grid-cols-[repeat(${numcol},_1rem)]`}>
        {grid.map((row, i) =>
          row.map((col, j) => (
            <div
              onClick={() =>
                setGrid((grid) =>
                  produce(grid, (gridCopy) => {
                    gridCopy[i][j] === 1
                      ? (gridCopy[i][j] = 0)
                      : (gridCopy[i][j] = 1);
                  })
                )
              }
              key={`${i}-${j}`}
              className={`w-4 h-4 border-[1px] border-gray-200 transition-all ${
                grid[i][j] === 1 ? "bg-slate-800" : "bg-gray-50"
              }`}
            ></div>
          ))
        )}
      </div>
    </div>
  );
}

this is the index.js file in next template project. i'm using tailwind for css btw.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source