Imaginez incrémenter un compteur dans un composant:
class SomeComponent extends Component{
state = {
updatedByDiv: '',
updatedByBtn: '',
counter: 0
}
divCountHandler = () => {
this.setState({
updatedByDiv: 'Div',
counter: this.state.counter + 1
});
console.log('divCountHandler executed');
}
btnCountHandler = () => {
this.setState({
updatedByBtn: 'Button',
counter: this.state.counter + 1
});
console.log('btnCountHandler executed');
}
...
...
render(){
return (
...
// a parent div
<div onClick={this.divCountHandler}>
// a child button
<button onClick={this.btnCountHandler}>Increment Count</button>
</div>
...
)
}
}
Il existe un gestionnaire de comptage attaché aux composants parent et enfant. Ceci est fait exprès afin que nous puissions exécuter le setState () deux fois dans le même contexte de bullage d'événement de clic, mais à partir de 2 gestionnaires différents.
Comme nous l'imaginons, un seul événement de clic sur le bouton déclencherait maintenant ces deux gestionnaires puisque l'événement bouillonnait de la cible vers le conteneur le plus à l'extérieur pendant la phase de bullage.
Par conséquent, le btnCountHandler () s'exécute en premier, devrait incrémenter le nombre à 1, puis le divCountHandler () s'exécute, devrait incrémenter le nombre à 2.
Cependant, le nombre augmente uniquement à 1 comme vous pouvez l'inspecter dans les outils React Developer.
Cela prouve que réagissent
met en file d'attente tous les appels setState
revient dans cette file d'attente après avoir exécuté la dernière méthode dans le contexte (le divCountHandler dans ce cas)
fusionne toutes les mutations d'objet qui se produisent dans plusieurs appels setState dans le même contexte (tous les appels de méthode dans une seule phase d'événement sont le même contexte pour, par exemple) en une seule syntaxe de mutation d'objet (la fusion a du sens car c'est pourquoi nous pouvons mettre à jour les propriétés de l'état indépendamment dans setState () en premier lieu)
et le transmet à un seul setState () pour empêcher le re-rendu dû à plusieurs appels à setState () (c'est une description très primitive du traitement par lots).
Code résultant exécuté par react:
this.setState({
updatedByDiv: 'Div',
updatedByBtn: 'Button',
counter: this.state.counter + 1
})
Pour arrêter ce comportement, au lieu de passer des objets en tant qu'arguments à la méthode setState, des rappels sont passés.
divCountHandler = () => {
this.setState((prevState, props) => {
return {
updatedByDiv: 'Div',
counter: prevState.counter + 1
};
});
console.log('divCountHandler executed');
}
btnCountHandler = () => {
this.setState((prevState, props) => {
return {
updatedByBtn: 'Button',
counter: prevState.counter + 1
};
});
console.log('btnCountHandler executed');
}
Une fois que la dernière méthode a terminé son exécution et que react revient pour traiter la file d'attente setState, elle appelle simplement le rappel pour chaque setState mis en file d'attente, en passant l'état précédent du composant.
De cette façon, react garantit que le dernier rappel de la file d'attente met à jour l'état sur lequel tous ses homologues précédents ont mis la main.