【问题标题】:ReactJs. the function is called before the state is updated反应。在状态更新之前调用该函数
【发布时间】:2019-03-14 10:41:26
【问题描述】:

我正在编写 Snake 游戏应用程序以进行练习。

我有一个 changeDirection 函数,它根据箭头单击将适当的方向设置为状态:

changeDirection = event => {
  const { direction } = this.state;

  const keyPressed = event.keyCode;

  if (keyPressed === keyCodes.LEFT_KEY && direction !== "right") {
    this.setState({ direction: "left" });
  }
  if (keyPressed === keyCodes.UP_KEY && direction !== "down") {
    this.setState({ direction: "up" });
  }
  if (keyPressed === keyCodes.RIGHT_KEY && direction !== "left") {
    this.setState({ direction: "right" });
  }
  if (keyPressed === keyCodes.DOWN_KEY && direction !== "up") {
    this.setState({ direction: "down" });
  }
}

它工作正常,但问题出在另一个函数中。 我正在根据方向状态更新蛇的头部位置。并且此函数每 1 秒执行一次(使用 setInterval),当方向改变时,蛇的头部不会立即改变方向。它会在下一步行动。

我知道这是因为蛇第一次移动时新的方向状态尚未设置,但我不知道如何解决这个问题。

这里是回购: https://github.com/Dito-Orkodashvili/snake

【问题讨论】:

  • 请包含所有相关代码。无法说出您问题中当前的代码可能有什么问题。
  • 我已经在原帖中添加了repo链接。

标签: reactjs asynchronous setstate


【解决方案1】:

你可以用这个。

   this.setState({ direction: "down" },anotherFunction());

在setState的回调中调用你的函数,状态更新后调用。

链接:https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296

【讨论】:

  • 这似乎是正确的。但是,如果他的函数每秒都使用setInterval 调用,那么代码应该可以正常工作:1)changeDirection() 改变状态。 2)最终,setInterval 将调用函数changeHeadPosition(),它会在(1)点之后。所以,我不知道他为什么会遇到问题。@Dito 也许你也应该展示其他功能
  • 我知道,但问题是我在其他地方称其为“anotherFunction”。 p.s 我把整个 repo 链接放到了原帖中
  • 这应该是this.setState({ direction: "down" }, anotherFunction);,除非 anotherFunction 返回一个函数
【解决方案2】:

您只是在更新方向的状态。这使得组件重新渲染。然后你更新蛇的状态,组件重新渲染,然后你看到头部更新了。

解决方案可能是分解 moveSnake 函数。组件渲染后,仅使用 moveSnake 移动蛇。

创建另一个函数来更新头部和蛇的状态并从键盘事件处理程序中调用它。这样,组件将同时重新渲染状态的所有更改。

从 setInterval 更新状态也应该有效,如下所示:

newDirection;

startGame = () => {
   this.interval = setInterval(() => {
     this.moveSnake();
   }, 200);
};

changeDirection = event => {
    const keyPressed = event.keyCode;

    if (keyPressed === keyCodes.LEFT_KEY && direction !== 'right') {
      this.newDirection = 'left';
    }
    if (keyPressed === keyCodes.UP_KEY && direction !== 'down') {
      this.newDirection = 'up';
    }
    if (keyPressed === keyCodes.RIGHT_KEY && direction !== 'left') {
      this.newDirection = 'right';
    }
    if (keyPressed === keyCodes.DOWN_KEY && direction !== 'up') {
      this.newDirection = 'down';
    }
};

moveSnake = () => {
   /* do updates in the snake shape */

   this.setState({
     direction: this.newDirection,
     snake: copyOfSnake
   });
};

【讨论】:

  • 这正是正在发生的事情,但我认为您的解决方案不适合我的情况。因为我使用 setInterval 每秒都在更新蛇头的位置。这就是蛇的移动方式。它将头部向前移动一个单元并去除尾部。所以如果我只在 keyDown 事件中调用这个函数,那么在我按下按钮之前蛇不会移动。如果我错了,请纠正我。
  • 那么一个解决方案可能是不直接从事件处理程序更新状态,而是存储方向值。然后使用您的方向变量从 setInterval 更新状态。
猜你喜欢
  • 2021-05-01
  • 1970-01-01
  • 2021-12-18
  • 2017-09-16
  • 2023-01-28
  • 2023-02-26
  • 2019-08-04
  • 1970-01-01
  • 2018-12-08
相关资源
最近更新 更多