47 votes

Pourquoi l'appel de la méthode setState ne mute pas l'état immédiatement?

Ok, je vais essayer de le faire rapidement parce que ça DEVRAIT être une solution facile...

J'ai lu un tas de questions similaires, et la réponse semble assez évidente. Rien de je pourrais jamais avoir à rechercher en premier lieu! Mais... je vais avoir une erreur que je ne peux pas imaginer comment réparer ou pourquoi il n'arrive.

Comme suit:

class NightlifeTypes extends Component {
constructor(props) {
    super(props);

    this.state = {
        barClubLounge: false,
        seeTheTown: true,
        eventsEntertainment: true,
        familyFriendlyOnly: false
    }
    this.handleOnChange = this.handleOnChange.bind(this);
}

handleOnChange = (event) => {   
    if(event.target.className == "barClubLounge") {
        this.setState({barClubLounge: event.target.checked});
        console.log(event.target.checked)
        console.log(this.state.barClubLounge)
    }
}

render() {
    return (
        <input className="barClubLounge" type='checkbox' onChange={this.handleOnChange} checked={this.state.barClubLounge}/>
    )
}

Plus de code entoure mais c'est là que mon problème se situe. Devrait fonctionner, non?

J'ai aussi essayé ceci:

handleOnChange = (event) => {   
if(event.target.className == "barClubLounge") {
    this.setState({barClubLounge: !this.state.barClubLounge});
    console.log(event.target.checked)
    console.log(this.state.barClubLounge)
}

J'ai donc ces deux - console.log()s', les deux devraient être les mêmes. Je suis littéralement réglage de l'etat est la même que l' event.target.checked dans la ligne au-dessus d'elle!

Mais il renvoie toujours à l'opposé de ce qu'il devrait.

En va de même pour quand j'utilise !this.state.barClubLounge; Si elle commence à faux, sur mon premier clic, il reste faux, même si la si la case est cochée ou non est basé hors de l'état!!

C'est un fou paradoxe et je n'ai aucune idée de ce qui se passe, s'il vous plaît aider!

54voto

Mayank Shukla Points 39317

La raison est setState est asynchrone, vous ne pouvez pas attendre la mise à jour de state de la valeur juste après l' setState,, si vous voulez vérifier la valeur de l'utilisation d'un callback méthode. Passer d'une méthode de callback qui sera exécutée après l' setState mener sa tâche à bien.

Pourquoi setState est asynchrone ?

C'est parce qu' setState modifie l' state et provoque un re de rendu. Ce peut être une opération coûteuse et rendant synchronous pourrait quitter le navigateur ne répond pas. Ainsi, l' setState des appels sont asynchronous ainsi que des lots pour une meilleure expérience de l'INTERFACE utilisateur et la performance.

De Doc:

setState() ne prend pas immédiatement muter cette.l'état crée un dans l'attente de transition d'état. L'accès à ce.état après l'appel de cette la méthode peut peut-être retourner à la valeur existante. Il n'y a pas de garantie de fonctionnement synchrone des appels à setState et les appels peuvent être groupées pour des gains de performance.

À l'aide de la méthode de rappel avec setState:

De vérifier la mise à jour de state de la valeur juste après l' setState, utilisez une méthode de rappel comme ceci:

setState({ key: value }, () => {
     console.log('updated state value', this.state.key)
})

Vérifiez ceci:

class NightlifeTypes extends React.Component {
   constructor(props) {
      super(props);

      this.state = {
         barClubLounge: false,
         seeTheTown: true,
         eventsEntertainment: true,
         familyFriendlyOnly: false
      }
   }

   handleOnChange = (event) => {  // Arrow function binds `this`
      let value = event.target.checked;

      if(event.target.className == "barClubLounge") {

         this.setState({ barClubLounge: value}, () => {  //here
             console.log(value);
             console.log(this.state.barClubLounge);
             //both will print same value
         });        

      }
   }

   render() {
      return (
          <input className="barClubLounge" type='checkbox' onChange={this.handleOnChange} checked={this.state.barClubLounge}/>
      )
   }
}

ReactDOM.render(<NightlifeTypes/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app'/>

2voto

Asif J Points 787

Depuis setState est une fonction asynchrone. Cela signifie qu'après l'appel de la variable d'état setState, cela ne change pas immédiatement. Par conséquent, si vous souhaitez effectuer d'autres actions immédiatement après la modification de l'état, vous devez utiliser la méthode de rappel de setstate dans votre fonction de mise à jour de setState.

 handleOnChange = (event) => { 
     let inputState = event.target.checked;
      if(event.target.className == "barClubLounge") {
         this.setState({ barClubLounge: inputState}, () => {  //here
             console.log(this.state.barClubLounge);
             //here you can call other functions which use this state 
             variable //
         });        
      }
   }
 

0voto

Nir O. Points 454

Ceci est dû à des considérations de performances. setState dans React est une fonction garantie pour restituer Component, processus coûteux du processeur. En tant que tels, ses concepteurs voulaient optimiser en regroupant plusieurs actions de rendu en une seule et ainsi, setState est asynchrone.

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