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

问题描述 投票:6回答:2

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

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

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

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)它可以工作但第二次冻结。有人可以帮帮我吗?

javascript reactjs callback setstate
2个回答
2
投票

我会看看你正在设置this.Dungeon.map状态的部分。

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

                this.generateGamePlay();

          })

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

来自react docs

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

当你将map属性传递给setstate时,它将保留对this.Dungeon.map的引用,如果你修改它将导致问题。你应该复制.map的副本并将其传递给state。

您还应该制作一个负责状态的组件,而不是在不同的功能中多次调用它。来自react docs

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

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

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


0
投票

就像弗兰克的代码一样,我有这个:

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

我希望这对你来说很方便,或者说我做错了,或者误解了你的问题

© www.soinside.com 2019 - 2024. All rights reserved.