État local de composant

Que fait setState ?

setState() planifie la mise à jour de l’objet state du composant. Quand l’état local change, le composant répond en se rafraîchissant.

Quelle est la différence entre state et props ?

props (diminutif de « propriétés ») et state sont tous les deux des objets JavaScript bruts. Même s’ils contiennent tous les deux des informations qui influencent le résultat produit, ils présentent une différence majeure : props est passé au composant (à la manière des arguments d’une fonction) tandis que state est géré dans le composant (comme le sont les variables déclarées à l’intérieur d’une fonction).

Voici quelques ressources utiles pour mieux comprendre selon quels critères choisir entre props et state :

Pourquoi setState me renvoie-t-elle une valeur incorrecte ?

En React, this.props et this.state représentent l’un comme l’autre les valeurs du rendu, c’est-à-dire ce qui est actuellement affiché.

Les appels à setState sont asynchrones : ne comptez pas sur this.state pour refléter la nouvelle valeur immédiatement après avoir appelé setState. Passez une fonction de mise à jour à la place d’un objet si vous devez calculer des valeurs en fonction de l’état actuel (voir ci-dessous pour plus de détails).

Voici un exemple de code qui ne se comporte pas comme attendu :

incrementCount() {
  // Attention : ça ne va *pas* fonctionner comme prévu.
  this.setState({count: this.state.count + 1});
}

handleSomething() {
  // Disons que `this.state.count` commence à 0.
  this.incrementCount();
  this.incrementCount();
  this.incrementCount();
  // Lorsque React rafraîchira le composant, `this.state.count` sera à 1,
  // pourtant, on s'attendait à 3.

  // C'est parce que la fonction `incrementCount()` ci-dessus lit `this.state.count`,
  // mais React ne met pas à jour `this.state.count` tant que le composant n'est pas rafraîchi.
  // Du coup `incrementCount()` lit `this.state.count` qui est égal à 0 à chaque fois,
  // et le définit à 1.

  // Le correctif est décrit ci-dessous !
}

Voir ci-dessous pour savoir comment résoudre ce problème.

Comment mettre à jour l’état avec des valeurs qui dépendent de l’état actuel ?

Passez une fonction au lieu d’un objet à setState pour vous assurer que l’appel utilise toujours la version la plus récente de l’état (voir ci-dessous).

Quelle est la différence entre passer un objet ou une fonction à setState ?

Passer une fonction de mise à jour vous permet d’accéder à la valeur à jour de l’état actuel au sein de cette fonction. Comme les appels setState sont groupés par lots, ça vous permet d’enchaîner les mises à jour et de vous assurer qu’elles sont effectuées les unes après les autres au lieu d’entrer en conflit :

incrementCount() {
  this.setState((state) => {
    // Important : lisez `state` au lieu de `this.state` lors de la mise à jour.
    return {count: state.count + 1}
  });
}

handleSomething() {
  // Disons que `this.state.count` commence à 0.
  this.incrementCount();
  this.incrementCount();
  this.incrementCount();

  // Si vous lisiez `this.state.count` maintenant, il serait toujours à 0.
  // Mais quand React rafraîchira le composant, il vaudra bien 3.
}

En apprendre davantage sur setState

Quand setState est-elle asynchrone ?

Actuellement, setState est asynchrone à l’intérieur des gestionnaires d’événements.

Ça permet de garantir, par exemple, que si Parent et Child appellent tous les deux setState lors d’un clic, Child ne sera pas rafraîchi deux fois. Au lieu de ça, React « apure » les mises à jour de l’état à la fin de l’événement du navigateur. Ça permet une amélioration significative des performances pour les applications de grande ampleur.

Il s’agit d’un détail d’implémentation donc évitez de vous appuyer dessus. Dans de futures versions, React groupera par défaut les mises à jour dans davantage encore de cas de figure.

Pourquoi React ne met-il pas à jour this.state de façon synchrone ?

Comme expliqué dans la section précédente, React « attend » volontairement que tous les composants aient fini d’appeler setState() dans leurs gestionnaires d’événements avant de commencer à mettre à jour les rendus. Ça améliore les performances en évitant des rafraîchissements inutiles.

Cependant, vous vous demandez peut-être toujours pourquoi React ne met pas juste à jour this.state immédiatement sans rafraîchir.

Il y a deux raisons principales :

  • Ça briserait la cohérence entre props et state, entraînant des problèmes très difficiles à déboguer.
  • Ça rendrait certaines nouvelles fonctionnalités sur lesquelles nous travaillons impossibles à implémenter.

Ce commentaire GitHub entre dans le détail d’exemples spécifiques.

Devrais-je utiliser une bibliothèque de gestion d’état, comme par exemple Redux ou Mobx ?

Peut-être.

Bien connaître React avant d’ajouter des bibliothèques supplémentaires reste une bonne idée. Vous pouvez créer des applications plutôt complexes en utilisant uniquement React.