Lorsqu'un état du composant de réaction change, la méthode de rendu est appelée. Par conséquent, pour tout changement d'état, une action peut être effectuée dans le corps des méthodes de rendu. Existe-t-il un cas d'utilisation particulier pour le rappel setState?
Oui, puisque setState
fonctionne de manière asynchronous
. Cela signifie qu'après avoir appelé setState
, la variable this.state
n'est pas immédiatement modifiée. donc si vous voulez exécuter une action immédiatement après avoir défini l'état d'une variable d'état, puis renvoyer un résultat, un rappel sera utile
Considérons l'exemple ci-dessous
....
changeTitle: function changeTitle (event) {
this.setState({ title: event.target.value });
this.validateTitle();
},
validateTitle: function validateTitle () {
if (this.state.title.length === 0) {
this.setState({ titleError: "Title can't be blank" });
}
},
....
Le code ci-dessus peut ne pas fonctionner comme prévu car la variable title
n'a peut-être pas muté avant la validation. Vous pouvez maintenant vous demander que nous pouvons effectuer la validation dans la fonction render()
elle-même, mais ce serait mieux et plus simple si nous pouvions le gérer dans la fonction changeTitle, car cela rendrait votre code plus organisé et plus compréhensible.
Dans ce cas, le rappel est utile
....
changeTitle: function changeTitle (event) {
this.setState({ title: event.target.value }, function() {
this.validateTitle();
});
},
validateTitle: function validateTitle () {
if (this.state.title.length === 0) {
this.setState({ titleError: "Title can't be blank" });
}
},
....
Un autre exemple sera lorsque vous voulez dispatch
et une action lorsque l'état a changé. vous souhaiterez le faire dans un rappel et non dans la render()
car il sera appelé à chaque fois qu'un rendu est effectué. Par conséquent, de nombreux scénarios sont possibles dans lesquels vous aurez besoin d'un rappel.
n autre cas est un API Call
Un cas peut se présenter lorsque vous devez effectuer un appel d'API en fonction d'un changement d'état particulier. Si vous le faites dans la méthode de rendu, il sera appelé à chaque changement de rendu onState
ou parce que certains Prop transmis à la Child Component
changé.
Dans ce cas, vous voudrez utiliser un setState callback
pour transmettre la valeur d'état mise à jour à l'appel d'API.
....
changeTitle: function (event) {
this.setState({ title: event.target.value }, () => this.APICallFunction());
},
APICallFunction: function () {
// Call API with the updated value
}
....
Le 1. cas d'utilisation qui me vient à l'esprit est un appel api
, qui ne doit pas entrer dans le rendu, car il s'exécutera pour le changement d'état each
. Et l'appel de l'API doit être effectué uniquement lors d'un changement d'état spécial, et non le rendu tous.
changeSearchParams = (params) => {
this.setState({ params }, this.performSearch)
}
performSearch = () => {
API.search(this.state.params, (result) => {
this.setState({ result })
});
}
Par conséquent, pour tout changement d'état, une action peut être effectuée dans le corps des méthodes de rendu.
Très mauvaise pratique, parce que la méthode render
- doit être pure, cela signifie qu'aucune action, changement d'état, appel d'api ne doit être effectué, composez simplement votre vue et renvoyez-la. Les actions doivent être effectuées sur certains événements uniquement. Le rendu n'est pas un événement, mais componentDidMount
par exemple.
this.setState({
name:'value'
},() => {
console.log(this.state.name);
});
Envisager un appel à setState
this.setState({ counter: this.state.counter + 1 })
IDÉE 1
setState peut être appelé en fonction asynchrone
Donc, vous ne pouvez pas compter sur this
. Si l'appel ci-dessus a été effectué à l'intérieur d'une fonction asynchrone, this
fera référence à l'état du composant à ce moment-là, mais nous nous attendions à ce qu'il fasse référence à une propriété à l'intérieur de l'état à l'heure à l'appel de setState ou au début de la tâche async. Et comme tâche était un appel asynchrone, cette propriété peut avoir changé dans le temps. Ainsi, il n'est pas fiable d'utiliser le mot clé this
pour faire référence à une propriété d'état. Nous utilisons donc une fonction de rappel dont les arguments sont previousState et props, ce qui signifie que la tâche asynchrone était terminée et qu'il était temps de mettre à jour l'état à l'aide de setState. indiquer maintenant quand setState n'a pas encore commencé. Assurer la fiabilité que nextState ne serait pas corrompu.
Mauvais code: conduirait à la corruption de données
this.setState(
{counter:this.state.counter+1}
);
Code correct avec setState ayant une fonction de rappel:
this.setState(
(prevState,props)=>{
return {counter:prevState.counter+1};
}
);
Ainsi, chaque fois que nous devons mettre à jour notre état actuel sur l'état suivant en fonction de la valeur que possède actuellement la propriété et que tout ceci se produit de manière asynchrone, il est judicieux d'utiliser setState en tant que fonction de rappel.
IDÉE 2
L'appel setState peut être async
lui-même bcz React peut essayer de combiner deux ou plusieurs appels setState ensemble pour performance amélioration. De toute façon, ce n'est pas fiable. Supposons que deux appels setState soient déclenchés à t =. Ils faisaient tous deux référence au même état (state_0) avant l’appel, étant asynchrone, nous ne pouvons pas compter sur celui qui se terminera le premier. Supposons qu'un appel puisse mener à state_1 lorsque l'un d'eux se termine. Et un autre appel où l’état faisait référence à l’état initial (state_0) peut conduire à state_3 . Et cela peut conduire à la corruption des états et de ses données. Utilisation d'un rappel où les arguments de la fonction de rappel sont prevState, props. Il s'assure que si l'une d'elles se termine en premier par state_1, le prochain setState référencera toujours prevState en tant qu'état initial. Ainsi, assurez-vous toujours que les données ne sont pas corrompues. Il est très peu probable que les données soient corrompues de cette façon, car setState est appelé simultanément. Mais si nous devons que notre prochain état soit dépendant de prevState, utilisez toujours callback.
J'ai essayé de l'expliquer dans codepen iciCODE PEN