294 votes

Quand utiliser le callback setState de React

Lorsqu'un état d'un composant React change, la méthode de rendu est appelée. Ainsi, 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 de setState alors?

4 votes

Il est actuellement peu clair de savoir ce que vous demandez. Pouvez-vous inclure du code?

4 votes

Le rappel de setState est pour tout ce que vous voulez faire après que l'état ait DEFINITIVEMENT été modifié. Puisque setState est asynchrone, si vous voulez appeler une fonction et être SÛR que le nouvel état est chargé, c'est à cela que sert le rappel

4 votes

Le cas d'utilisation du rappel de setState est assez clair. Vous l'utilisez lorsque vous voulez qu'une fonction s'exécute après qu'un état SPÉCIFIQUE a été mis à jour. Si vous mettez cette fonction dans render() à la place, elle s'exécutera à chaque fois qu'un ÉTAT quelconque est mis à jour, ce qui n'est probablement pas ce que vous voulez. Cela rendra également votre code moins lisible et logique.

325voto

Shubham Khatri Points 67350

Oui, il y en a, car setState fonctionne de manière asynchrone. Cela signifie qu'après avoir appelé setState, la variable this.state n'est pas immédiatement modifiée. Donc si vous souhaitez effectuer 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érez 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: "Le titre ne peut pas être vide" });
  }
},
....

Le code ci-dessus peut ne pas fonctionner comme prévu car la variable title peut ne pas avoir été modifiée avant la validation. Vous pourriez vous demander si nous pouvons effectuer la validation dans la fonction render() elle-même, mais il serait mieux et plus propre si nous pouvons gérer cela dans la fonction changeTitle elle-même car cela rendrait votre code plus organisé et 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: "Le titre ne peut pas être vide" });
  }
},
....

Un autre exemple serait lorsque vous voulez dispatch une action lorsque l'état change. vous voudrez le faire dans un rappel et non dans le render() car il sera appelé à chaque nouvelle rendu onState ou lorsque certaines props transmises à le Composant Enfant changé.

Un autre cas est un Appel API

Un cas peut se présenter lorsque vous avez besoin de faire un appel API en fonction d'un changement d'état particulier, si vous le faites dans la méthode render, il sera appelé à chaque rendu onState changement ou parce que certaines Prop transmises au Composant Enfant ont changé.

Dans ce cas, vous voudrez utiliser un rappel de setState pour transmettre la valeur d'état mise à jour à l'appel API

....
changeTitle: function (event) {
  this.setState({ title: event.target.value }, () => this.FonctionAppelAPI());
},
FonctionAppelAPI: function () {
  // Appeler l'API avec la valeur mise à jour
}
....

5 votes

Je comprends que c'est asynchrone par nature. Ma question était y a-t-il quelque chose de spécifique que seul le rappel de setState peut être utilisé pour peut-être un corps de méthodes de rendu ne prend pas en charge (Quelque chose en dehors, disons une meilleure lisibilité du code.)

0 votes

@SahilJain La validation est le bon exemple, vous ne voudrez pas la gérer dans la fonction render() car elle serait alors appelée à chaque fois que vous apportez une modification dans la fonction render(), vous voudriez l'appeler uniquement lorsque l'entrée change et donc dans la fonction elle-même.

0 votes

React interdit de modifier l'état pendant le rendu. Il est donc juste de placer la validation dans le rappel.

76voto

Araz Babayev Points 507
this.setState({
    name:'valeur' 
},() => {
    console.log(this.state.name);
});

28 votes

Merci pour cet extrait de code, qui pourrait fournir une aide limitée et immédiate. Une explication correcte améliorerait considérablement sa valeur à long terme en montrant pourquoi il s'agit d'une bonne solution au problème, et le rendrait plus utile aux futurs lecteurs ayant d'autres questions similaires. Veuillez modifier votre réponse pour ajouter une explication, y compris les hypothèses que vous avez faites.

1 votes

Lorsque vous souhaitez appeler une fonction après que l'état ait changé, vous pouvez utiliser la méthode.

0 votes

Que se passe-t-il si vous voulez définir plusieurs propriétés de l'état comme le nom, le prénom, etc.?

48voto

webdeb Points 1383

Le 1er cas d'utilisation qui me vient à l'esprit est un appel api, qui ne devrait pas être placé dans le rendu, car il s'exécutera à chaque changement d'état. Et l'appel API ne doit être effectué que lors de changements d'état spéciaux, et non à chaque rendu.

changeSearchParams = (params) => {
  this.setState({ params }, this.performSearch)
} 

performSearch = () => {
  API.search(this.state.params, (result) => {
    this.setState({ result })
  });
}

Ainsi, pour tout changement d'état, une action peut être effectuée dans le corps des méthodes de rendu.

Très mauvaise pratique, car la méthode render doit être pure, ce qui signifie qu'aucune action, changement d'état, appel API, ne doivent être effectués, il vous suffit de composer votre vue et de la renvoyer. Les actions doivent être effectuées uniquement lors de certains événements. Le rendu n'est pas un événement, mais par exemple componentDidMount.

39voto

Aniket Jha Points 795

Considérez l'appel de setState

this.setState({ counter: this.state.counter + 1 })

IDÉE

setState peut être appelé dans une fonction asynchrone

Donc vous ne pouvez pas vous fier à this. Si l'appel ci-dessus a été fait à l'intérieur d'une fonction asynchrone, this fera référence à l'état du composant à ce moment-là, mais nous nous attendions à ce que cela fasse référence à la propriété à l'intérieur de l'état au moment de l'appel de setState ou au début de la tâche asynchrone. Et comme la tâche était un appel asynchrone, cette propriété a peut-être changé entre-temps. Il n'est donc pas fiable d'utiliser le mot-clé this pour faire référence à certaines propriétés de l'état, c'est pourquoi nous utilisons une fonction de rappel dont les arguments sont previousState et props, ce qui signifie que lorsque la tâche asynchrone est terminée et qu'il est temps de mettre à jour l'état en utilisant l'appel à setState, prevState fera référence à l'état au moment où setState n'a pas encore commencé. Assurant la fiabilité que le nextState ne sera pas corrompu.

Code incorrect : entraînerait une corruption des 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 vers l'état suivant en fonction de la valeur passée par la propriété juste maintenant, et tout cela se fait de manière asynchrone, il est une bonne idée d'utiliser setState avec une fonction de rappel.

J'ai essayé d'expliquer cela dans codepen ici CODE PEN

4voto

Abdul Azeem Points 187

Parfois, nous avons besoin d'un bloc de code où nous devons effectuer une opération juste après setState où nous sommes certains que l'état est en train d'être mis à jour. C'est là que le callback de setState entre en jeu

Par exemple, il y avait un scénario où je devais activer un modal pour 2 clients sur 20, pour les clients où nous l'avons activé, il y avait une série d'appels API prenant du temps, donc cela ressemblait à ceci

async componentDidMount() {
  const appConfig = getCustomerConfig();
  this.setState({enableModal: appConfig?.enableFeatures?.paymentModal }, async 
   ()=>{
     if(this.state.enableModal){
       //faire un appel API pour les données nécessaires dans le poput
     }
  });
}

enableModal boolean était nécessaire dans les blocs UI dans la fonction de rendu également, c'est pourquoi j'ai fait setState ici, sinon, j'aurais simplement vérifié la condition une fois et appelé ou non l'API.

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