web-dev-qa-db-fra.com

Utilisation de this.setState dans le rappel de this.setState dans React JS?

Est-il possible d'appeler this.setState dans le rappel de this.setState?

Je suis en train de faire un donjon Roguelike et j'ai une configuration dans laquelle, dans le rappel de this.setState, une fonction d'assistance est utilisée, qui appelle this.setState à nouveau. Mon jeu se fige à ce stade.

J'ai donc un objet dans le composant React qui a une méthode pour générer une carte de tableau 2D aléatoire:

this.Dungeon.Generate();

Lorsque le jeu démarre, nous appelons dans composantDidMount () la fonction suivante du composant:

componentDidMount: function() {

    this.Dungeon.Generate();

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

      this.generateGamePlay();

    });

  },

this.generateGamePlay () ressemble à ceci et génère et place le joueur, le boss et les objets au hasard sur le tableau:

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
});

 },

Mais lorsqu'un joueur meurt, nous appelons à nouveau ci-dessus pour réinitialiser le jeu:

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();

          })

Mais c'est quand mon jeu se fige. Ainsi, la première fois que j'appelle this.generateGamePlay () (qui appelle this.setState), cela fonctionne, mais la deuxième fois, il se fige. Est-ce que quelqu'un peut m'aider?

6
chemook78

Je voudrais regarder la partie où vous définissez this.Dungeon.map en état.

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

                this.generateGamePlay();

          })

j'imagine que quelque chose d'autre pourrait modifier l'objet de la carte et ne pas utiliser setstate puisqu'il s'agit d'une propriété du donjon. 

à partir de la réagir docs

Ne modifiez jamais cet état directement, car appeler ensuite setState () peut Remplacer la mutation que vous avez effectuée. Traitez cet Etat comme s'il était Immuable.

lorsque vous transmettez la propriété map à setstate, elle garde une référence à this.Dungeon.map qui, si vous le modifiez ensuite, causera des problèmes. Vous devriez faire une copie de ce que jamais est .map et le transmettre à l'état.

Vous devez également créer un composant responsable de l’état au lieu de l’appeler plusieurs fois dans différentes fonctions. À partir du réagir docs

setState () ne mute pas immédiatement this.state mais crée une transition d'état en attente. Accéder à this.state après avoir appelé cette méthode Peut potentiellement renvoyer la valeur existante.

Il n'y a aucune garantie de fonctionnement synchrone des appels à setState Et les appels peuvent être mis en lot pour des gains de performances.

votre blocage pourrait provenir de conditions de concurrence dans la méthode de rendu en raison de tous les appels multiples de setstate.

2
Frank