I have a bug in my code written with TypeScript & React

Hi, I have a bug with the code below. It is Tic Tac Toe project. But the board size can be changed by the user. When board size gets to certain threshold, amount of squares changes while keeping previous values too to make it a little fun. Size can be changed with mouse movement. But the problem is that, updateSquares() function inside the code gets called multiple times, in result resets all squares and sometimes does not even change the square amount. What can be done? Thanks in advance
Code:

import '../styles/Main.css';
import { Board } from './Board';
import { Square } from './Square';
import { useState, useEffect } from 'react';
export function Main(){
    interface Square {
        value: null | string,
        id: string
    }
    
    const [squares, setSquares] = useState((): Square[] => {
        return Array.from({ length: 9 }, (_, index) => ({
            value: null,
            id: `s${index}`,
        }));
    });
    const [grid, setGrid] = useState('three');
    const play = (id:string) => {
        const newSquares = JSON.parse(JSON.stringify(squares));
        const index = newSquares.findIndex((square:any) => square.id === id);
        if (newSquares[index].value) {
          return;
        }
      
        newSquares[index].value = 'X';
        setSquares(newSquares);
    };

    const updateSquares = (newSquares:any) => {
        const len = newSquares.length;
        setSquares(newSquares);
        setGrid(len === 9 ? 'three' : len === 16 ? 'four' : 'five');
        console.log('changed');
    }

    const checkResize = (newWidth: number, newHeight: number, squares: any) => {
        newWidth = Math.abs(newWidth);
        newHeight = Math.abs(newHeight);
        if (newWidth <= 300 && newHeight <= 300 && squares.length !== 9) {
            const newSquares = squares.filter((square:any) => Number.parseInt(square.id.slice(1)) < 9);
            const temp = (new Array(9)).fill(null);
            for(let i = 0; i < temp.length; i++){
                temp[i] = { ...newSquares[i] };
            }

            return [...temp];
        }else if ((380 <= newWidth && newWidth <= 450) && (380 <= newHeight || newHeight <= 450) && squares.length !== 16){
            if(squares.length === 9){
                const newSquares: Square[] = Array.from({ length: 16 }, (_, index) => ({
                    value: null,
                    id: `s${index}`,
                }));

                for(let i = 0; i < squares.length; i++){
                    newSquares[i] = {...squares[i]};
                }

                let temp = newSquares.splice(3, 1);
                let temp2 = newSquares[9];

                newSquares.splice(3, 0, temp2);

                newSquares.splice(10, 1);

                newSquares.splice(4, 0, temp[0]);

                temp = newSquares.splice(7, 1);
                temp2 = newSquares[10];

                newSquares.splice(7, 0, temp2);

                newSquares.splice(11, 1);

                newSquares.splice(8, 0, temp[0]);
                return [...newSquares];

            }else{
                const newSquares = squares.filter((square:any) => Number.parseInt(square.id.slice(1)) < 16);
                const temp = (new Array(16)).fill(null);
                for(let i = 0; i < temp.length; i++){
                    temp[i] = { ...newSquares[i] };
                }

                return [...temp];
            }
        }else{
            return [...squares];
        }
    };

    useEffect(() => {
        const resizable = document.querySelector('.board') as HTMLDivElement;
        const handle = document.querySelector('.resize') as HTMLDivElement;
        let startX: any, startY: any, startWidth: any, startHeight: any;
        let isResizing: any;

        const handleMouseDown = (e: MouseEvent) => {
          if (e.button !== 0) {
            isResizing = false;
          } else {
            isResizing = true;
          }
    
          startX = e.clientX;
          startY = e.clientY;
          startWidth = parseInt(document.defaultView!.getComputedStyle(resizable).width, 10);
          startHeight = parseInt(document.defaultView!.getComputedStyle(resizable).height, 10);
        };
    
        const handleMouseMove = (e: MouseEvent) => {
          if (!isResizing) return;
    
          const Width = startWidth - (e.clientX - startX) * 3;
          const Height = startHeight - (e.clientY - startY) * 3;
    
          const newWidth = Math.max(Width, Height);
          const newHeight = Math.max(Height, Width);
    
          let widthFlag = false;
          let heightFlag = false;
    
          if (!(550 < newWidth || newWidth < 150)) {
            resizable.style.width = `${newWidth}px`;
            widthFlag = true;
          } else {
            widthFlag = false;
          }
    
          if (!(550 < newHeight || newHeight < 150)) {
            resizable.style.height = `${newHeight}px`;
            heightFlag = true;
          } else {
            heightFlag = false;
          }
          
          if (widthFlag || heightFlag) {
            const newSquares = checkResize(newWidth, newHeight, squares);
            if(newSquares.length !== squares.length){
                updateSquares(newSquares);
            }
          }
        };
    
        const handleMouseUp = () => {
          isResizing = false;
        };
    
        handle.addEventListener('mousedown', handleMouseDown);
        document.addEventListener('mousemove', handleMouseMove);
        document.addEventListener('mouseup', handleMouseUp);
    
        return () => {
          handle.removeEventListener('mousedown', handleMouseDown);
          document.removeEventListener('mousemove', handleMouseMove);
          document.removeEventListener('mouseup', handleMouseUp);
        };
      }, []);
    return(
        <main>
            <section className='tictactoe'>
                <div className="game-wrapper">
                    <div className='board-wrapper'>
                        <Board className={`board ${grid}`}>
                            {squares.map((square:any, index:any) =>
                                <Square 
                                onClick={() => play(square.id)} 
                                key={index}
                                className='square' 
                                id={square.id}
                                x={square.value === 'X' ? 1 : 0} 
                                o={square.value === 'O' ? 1 : 0} />
                            )}
                        </Board>
                        <div className='resize' draggable='false'></div>
                    </div>
                </div>
            </section>
        </main>
    );
}

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.