在 React JS 中 this.setState 的回调中使用 this.setState?

IT技术 javascript reactjs callback setstate
2021-05-03 13:45:12

是否可以在 this.setState 的回调中调用 this.setState?

我正在制作一个 Roguelike Dungeon 并有一个设置,其中在 this.setState 的回调中使用了一个辅助函数,它再次调用 this.setState。我的游戏在这一点上冻结。

所以我在 React 组件中有一个对象,它有一个生成随机二维数组映射的方法:

this.Dungeon.Generate();

当游戏开始时,我们在 componentDidMount() 中调用组件中的以下函数:

componentDidMount: function() {

    this.Dungeon.Generate();

    this.setState({
      board: this.Dungeon.map
    }, function() {

      this.generateGamePlay();

    });

  },

this.generateGamePlay() 看起来像这样,基本上是在棋盘上随机生成和放置玩家、老板和物品:

generateGamePlay: function() {

var board = this.state.board.slice();

var startPosition = this.randomPosition();

board[startPosition[0]][startPosition[1]] = this.state.player;

var bossPosition = this.randomPosition();

board[bossPosition[0]][bossPosition[1]] = this.state.boss[this.state.dungeonLevel];

this.generateWeapons(this.state.dungeonLevel,board);

this.generateFood(this.state.dungeonLevel, board);

this.generateEnemies(this.state.dungeonLevel, board);

this.setState({
  board: board
});

 },

但是当玩家死亡时,我们再次调用上面的方法来重置游戏:

this.Dungeon.Generate();
        //generate a new dungeon map, available in this.Dungeon.map

        this.setState({
          board: this.Dungeon.map, currentMessage: "Game restarted", player: player, weapon: weapon, dungeonLevel: 0
          }, function(){

                this.generateGamePlay();

          })

但那时我的游戏就死机了。因此,我第一次调用 this.generateGamePlay()(调用 this.setState)时它可以工作,但第二次它会冻结。任何人都可以帮助我吗?

2个回答

我会看看你在 state 中设置 this.Dungeon.map 的部分。

this.setState({
          board: this.Dungeon.map, currentMessage: "Game restarted", player: player, weapon: weapon, dungeonLevel: 0
          }, function(){

                this.generateGamePlay();

          })

我的猜测是其他东西可能会改变地图对象而不是使用 setstate,因为它是 Dungeon 的一个属性。

来自react文档

永远不要直接改变 this.state,因为之后调用 setState() 可能会替换你所做的改变。将 this.state 视为不可变的。

当您将 map 属性传递给 setstate 时,它​​将保留对 this.Dungeon.map 的引用,如果您随后修改会导致问题。您应该复制 .map 的内容并将其传递给 state。

您还应该让一个组件负责状态,而不是在不同的函数中多次调用它。来自react文档

setState() 不会立即改变 this.state 而是创建一个挂起的状态转换。调用此方法后访问 this.state 可能会返回现有值。

无法保证对 setState 调用的同步操作,并且可能会批量调用以提高性能。

由于所有多个 setstate 调用,您的冻结可能来自渲染方法中的竞争条件。

像弗兰克的代码我有这个:

this.setState( state => {
  state.board = this.Dungeon.map
  return state
})

我希望它对你有用,或者我做错了,或者误解了你的问题