【问题标题】:Event handler not picking up correct state value事件处理程序未获取正确的状态值
【发布时间】:2021-03-18 08:31:26
【问题描述】:

我正在开发一个简单的 Battleships 棋盘游戏,当玩家点击具有有效移动的单元格时需要增加一个状态变量。

代码沙盒:https://codesandbox.io/s/trusting-leakey-6ek9o

  • 与此问题相关的所有代码都可以在以下文件中找到:>src>GameboardSetup>GameboardSetup.js

有问题的状态变量称为placedShips。它旨在跟踪已将多少艘船放置在板上。变量被初始化为 0 并且应该递增直到它达到一个设定的整数值:

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

当用户点击网格时,会触发一个 onClick 处理程序。如果单元格是有效单元格,则应将一艘船放入数组中,placedShips 的值应递增。当值增加时,会选择一艘新船以放置在随后的点击中。每艘新船都有不同的长度。

目前,当用户点击一个有效的网格单元格时,一艘船会被正确地放入数组中。随后的有效点击会出现问题,然后将同一艘船放入阵列中。这个问题是由 onClick 处理程序引起的,显然没有收到placedShips 的更新状态值。

虽然我可以从 { useEffect } 钩子中看到状态实际上是递增的,但我认为事件处理程序中的 placedShips 变量始终设置为 0。以下是我认为我已经验证了这个问题的方法。

这是 onClick 事件处理程序,包含状态变量的控制台日志:

const onClickHandler = (e) => {
    console.log(placedShips)
    let direction = ships[placedShips].direction;
    let start = parseInt(e.target.id);
    let end = start + ships[placedShips].length - 1;
    console.log(playerGameboard.checkIfShipPresent());
    if ((playerGameboard.checkValidCoordinates(direction, start, end)) && (!playerGameboard.checkIfShipPresent(direction, start, end))) {
        playerGameboard.placeShip(placedShips, direction, start, end);
        setPlacedShips(oldValue => oldValue + 1);
    }
}

这里是 { useEffect } 钩子,其中包含状态变量的另一个控制台日志:

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

通过选择多个有效单元格,这是控制台日志输出:

GameboardSetup.js:70 0     <--- Event handler console log
GameboardSetup.js:74 false
GameboardSetup.js:143 1     <--- useEffect console log
GameboardSetup.js:70 0
GameboardSetup.js:74 false
GameboardSetup.js:143 2
GameboardSetup.js:70 0
GameboardSetup.js:74 false
GameboardSetup.js:143 3

您可以看到事件处理程序控制台日志始终将 placedShips 报告为 0。而 { useEffect } 挂钩显示它随着每次连续点击而递增。

对于这个冗长的问题,我已经坚持了 2 周,并且没有取得任何重大进展。任何建议都会非常感激。

谢谢!

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    UI 渲染时不会更新您的 onClickHandle。把它移到你的回报中。它工作正常。无需使用humanSetUpGrid。只需从 createUiGrid 中获取结果。所以单元格会在应用渲染时更新。

    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}
              onClick={onClickHandler}
              onMouseOut={onMouseOutHandler}
              onMouseOver={onMouseOverHandler}
            />
          );
        });
        return result;
      };
    
     <div className="setup-grid">
        <Table grid={createUiGrid()} />
      </div>
    

    【讨论】:

    • 我做了建议的更改,但不幸的是我看到了一个无限循环。
    • @Tijm92 记得更改您的 createUIGrid。我已将其添加到我的答案中。
    • 非常感谢您的帮助,它现在可以正常工作(我可以修复一些错误)-非常感谢!
    猜你喜欢
    • 2016-05-26
    • 2021-11-02
    • 2021-05-09
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 2012-04-20
    • 2017-01-08
    • 1970-01-01
    相关资源
    最近更新 更多