130 votes

Réaction de setState pas mise à jour immédiatement

Je suis en train de travailler sur une tâche de l'application. C'est une version très simplifiée du code fautif. J'ai une case à cocher:

 <p><input type="checkbox"  name="area" checked={this.state.Pencil}   onChange={this.checkPencil}/> Writing Item </p>

Voici la fonction qui appelle la case à cocher:

checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
  }); 
  this.props.updateItem(this.state);
}

updateItem est une fonction qui est mappé à l'expédition de redux

function mapDispatchToProps(dispatch){
  return bindActionCreators({ updateItem}, dispatch);
}

Mon problème est que lorsque j'appelle la updateItem l'action et de la console.journal de l'état, il est toujours de 1 pas en arrière. Si la case n'est pas cochée et pas vrai, je suis toujours à l'état de véritable passé à la updateItem fonction. Dois-je appeler une autre fonction pour forcer l'état de mise à jour?

134voto

Ben Hare Points 2514

Vous devez appeler votre deuxième fonction en tant que rappel à setState, car setState se produit de manière asynchrone. Quelque chose comme:

 this.setState({pencil:!this.state.pencil}, myFunction)
 

Cependant, dans votre cas, puisque vous voulez que cette fonction soit appelée avec un paramètre, vous devrez être un peu plus créatif et peut-être créer votre propre fonction qui appelle la fonction dans les accessoires:

 myFunction = () => {
  this.props.updateItem(this.state)
}
 

Combinez ceux-ci ensemble et cela devrait fonctionner.

35voto

rossipedia Points 10922

L'appel setState() dans React est asynchrone, pour différentes raisons (principalement les performances). Sous les couvertures, React regroupera plusieurs appels à setState() dans une mutation à un seul état, puis restituera le composant une seule fois, plutôt que de le restituer à chaque changement d'état.

Heureusement, la solution est assez simple - setState accepte un paramètre de rappel:

 checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
  }, function () {
      this.props.updateItem(this.state);
  }.bind(this));
}
 

14voto

GBL Points 301

Lorsque vous êtes à la mise à jour de votre état en utilisant une propriété de l'état actuel, de Réagir de la documentation vous conseillons d'utiliser l'appel de la fonction de la version de setState à la place de l'objet.

Donc, setState((state, props) => {...}) au lieu de setState(object).

La raison en est qu' setState est plus d'une demande de l'état pour le changement plutôt que d'un changement immédiat. Réagir lots ceux - setState des appels pour l'amélioration de la performance.

Sens de l'état de la propriété vous êtes à la vérification peut ne pas être stable. C'est un écueil potentiel d'être conscient de.

Pour plus d'informations, voir la documentation ici: https://facebook.github.io/react/docs/react-component.html#setstate


Pour répondre à votre question, je le ferais.

checkPencil(){
    this.setState((prevState) => {
        return {
            pencil: !prevState.pencil
        };
    }, () => {
        this.props.updateItem(this.state)
    });
}

13voto

Alireza Points 40192

C'est parce qu'il arrive de manière asynchrone, signifie que dans le temps, qui pourrait ne pas obtenir la mise à jour encore...

Selon Réagir v. 16 de la documentation, vous devez utiliser une deuxième forme d' setState() qui accepte une fonction plutôt qu'un objet:

Mises À Jour D'État Peut Être Asynchrone

Réagir peut par lots de plusieurs setState() appels en une seule mise à jour pour les performances.

Parce que cette.des accessoires et de la ce.l'état peut être mis à jour de manière asynchrone, vous ne doit pas s'appuyer sur leurs valeurs pour le calcul de l'état suivant.

Par exemple, ce code peut ne pas mettre à jour le compteur:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

Pour la fixer, utiliser une deuxième forme de setState() qui accepte une fonction plutôt que d'un objet. Cette fonction recevra de l'état précédent comme premier argument, et les accessoires au moment de la mise à jour est appliquée en tant que deuxième argument:

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

2voto

lost9123193 Points 1687

J'ai utilisé les suggestions de rossipedia et de Ben Hare et ai procédé comme suit:

 checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
   }, this.updatingItem); 
}

updatingItem(){
    this.props.updateItem(this.state)
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X