无法使用状态挂钩增加状态变量

时间:2021-03-04 22:48:39

标签: reactjs

我正在开发一款游戏,当玩家点击游戏板上的有效动作时,我需要增加一个状态变量。验证移动和进行移动的功能已全部到位;但是,我目前无法通过使用相应的钩子来增加状态变量。

我一直在使用与状态挂钩的 React 文档中定义的相同的方法来增加变量:https://reactjs.org/docs/hooks-state.html


我在这里初始化状态变量:

    const [placedShips, setPlacedShips] = useState(0);

接下来,对游戏板中的每个单元格应用点击事件侦听器:

const setGameboardUp = () => {
        const gameboardArray = Array.from(document.querySelectorAll(".cell"));
        gameboardArray.forEach((cell) => {
            cell.addEventListener("click", (e) => {
                e.stopImmediatePropagation();
                let direction = currentShip().direction;
                let start = parseInt(cell.id);
                let end = start + currentShip().length - 1;
                if (playerGameboard.checkValidCoordinates(direction, start, end)) {
                    playerGameboard.placeShip(placedShips, direction, start, end);
                    console.log(placedShips + 1)
                    setPlacedShips(placedShips + 1);
                    console.log(placedShips)
                }
            });

不幸的是,“placedShips”状态变量仍为 0,因此我的游戏无法正常运行。我已经尝试使用以下函数,它仍然是 0:

setPlacedShips(1);

我有点不明白为什么会发生这种情况,并且在尝试其他几个修复程序时没有任何运气。作为参考,以下是我正在使用的完整组件:

let playerGameboard = gameboardFactory();

const GameboardSetup = () => {
    const [humanSetupGrid, setHumanSetupGrid] = useState([]);
    const [ships,_setShips] = useState([
        {
            name: 'carrier',
            length: 5,
            direction: 'horizontal'
        },
        {
            name: 'battleship',
            length: 4,
            direction: 'horizontal'
        },
        {
            name: 'cruiser',
            length: 3,
            direction: 'horizontal'
        },
        {
            name: 'submarine',
            length: 3,
            direction: 'horizontal'
        },
        {
            name: 'destroyer',
            length: 2,
            direction: 'horizontal'
        }]);
    const [placedShips, setPlacedShips] = useState(0);

    const createGrid = () => {
        const cells = [];
        for (let i = 0; i < 100; i++) {
            cells.push(0);
        };
    };
    
    const createUiGrid = () => {
        const cells = [];
        for (let i = 0; i < 100; i++) {
                cells.push(i);
        }
        let counter = -1;
        const result = cells.map((cell) => {
            counter++;
            return <div className='cell' id={counter} />;
        });
        setHumanSetupGrid(result);
    };

    const setUpPlayerGrid = () => {
        // createGrid('grid');
        createUiGrid();
    }

    const currentShip = () => {
        return ships[placedShips];
    };

    const setGameboardUp = () => {
        const gameboardArray = Array.from(document.querySelectorAll(".cell"));
        gameboardArray.forEach((cell) => {
            cell.addEventListener("click", (e) => {
                e.stopImmediatePropagation();
                let direction = currentShip().direction;
                let start = parseInt(cell.id);
                let end = start + currentShip().length - 1;
                if (playerGameboard.checkValidCoordinates(direction, start, end)) {
                    playerGameboard.placeShip(placedShips, direction, start, end);
                    console.log(placedShips + 1)
                    setPlacedShips(placedShips + 1);
                    console.log(placedShips)
                }
            });
            cell.addEventListener("mouseover", (e) => {
                e.stopImmediatePropagation();
                let direction = currentShip().direction;
                let start = parseInt(cell.id);
                let end = start + currentShip().length - 1;
                if (currentShip().direction === 'horizontal') {
                    const newShip = [];
                    if (playerGameboard.checkValidCoordinates(direction, start, end)) {
                        for (let i = start; i <= end; i++) {
                            newShip.push(i);
                        };
                        newShip.forEach((cell) => {
                            gameboardArray[cell].classList.add('test');
                        })
                    }
                } else {
                    const newShip = [];
                    if (playerGameboard.checkValidCoordinates(direction, start, end)) {
                        for (let i = start; i <= end; i += 10) {
                            newShip.push(i);  
                        };
                        newShip.forEach((cell) => {
                            gameboardArray[cell].classList.add('test');
                        })
                    }
                }
            })
            cell.addEventListener("mouseleave", (e) => {
                e.stopImmediatePropagation();
                let direction = currentShip().direction;
                let start = parseInt(cell.id);
                let end = start + currentShip().length - 1;
                if (currentShip().direction === 'horizontal') {
                    const newShip = [];
                    if (playerGameboard.checkValidCoordinates(direction, start, end)) {
                        for (let i = start; i <= end; i++) {
                            newShip.push(i);
                        };
                        newShip.forEach((cell) => {
                            gameboardArray[cell].classList.remove('test');
                        })
                    }
                } else {
                    const newShip = [];
                    if (playerGameboard.checkValidCoordinates(direction, start, end)) {
                        for (let i = start; i <= end; i += 10) {
                            newShip.push(i);  
                        };
                        newShip.forEach((cell) => {
                            gameboardArray[cell].classList.remove('test');
                        })
                    }
                }
            })
        });
    };

    useEffect(() => {
        setUpPlayerGrid();
        // setUpComputerGrid();
    }, []);

    useEffect(() => {
        console.log(humanSetupGrid)
    }, [humanSetupGrid]);

    // Re-render the component to enable event listeners to be added to generated grid
    useLayoutEffect(() => {
        setGameboardUp();
    });

    return (
        <div className="setup-container">
            <div className="setup-information">
                <p className="setup-information__p">Add your ships!</p>
                <button className="setup-information__btn">Rotate</button>
            </div>
            <div className="setup-grid">
                <Table grid={humanSetupGrid} />
            </div>
        </div>
    );
}

export default GameboardSetup;

如果有人对这里可能出现的问题有任何想法,我将非常感谢您的帮助!

谢谢。

1 个答案:

答案 0 :(得分:3)

placedShips 不会立即反映您对其所做的更改。请参阅:useState set method not reflecting change immediately

如果您希望由于 useEffect 更改值而发生某些事情,您应该使用 placedShipsuseEffect(() => { // do something here once placedShips has changed }, [placedShips]) 作为依赖项之一:

placedShips

请注意,如果您在该 useEffect 中记录 {{1}},它将显示更新的值。