Je souhaite modifier la valeur de la clé hasSubmit, comme dans la section First Code. Je sais que ce n'est pas recommandé. Mais le deuxième code est asynchrone et je ne veux pas utiliser la fonction de rappel de setState.

  • Quelle est la différence entre this.state et setState?
  • Existe-t-il un moyen de modifier immédiatement la valeur d'état hasSubmit?

Premier code:

this.state.hasSubmit = false
this.setState({})
//Code that will use `hasSubmit`.

Deuxième code:

this.setState({
   hasSubmit: false,
});
//Code that will use `hasSubmit`.

AJOUTER:

Le scénario est le suivant:

  1. hasSubmit définissez false dans getInitialState().
  2. hasSubmit devient false lorsque je clique sur le bouton submit.
  3. hasSubmit deviendra true lors de l'envoi.

Le premier clic submit ne pose aucun problème et hasSubmit sera défini sur true.

Mais le deuxième clic submit sera incorrect en utilisant le Second asynchronous code, car le hasSubmit est toujours true, tandis que le First Code peut résoudre le problème.

49
DanielJyc 8 mars 2016 à 15:10

5 réponses

Meilleure réponse

Voici ce que les React docs disent:

NE JAMAIS muter this.state directement, car appeler setState () par la suite peut remplacer la mutation que vous avez faite. Traitez cet état comme s'il était immuable.

setState() ne mute pas immédiatement this.state mais crée une transition d'état en attente. Accéder à this.state après avoir appelé cette méthode peut potentiellement renvoyer la valeur existante.

Il n'y a aucune garantie de fonctionnement synchrone des appels vers setState et les appels peuvent être groupés pour des gains de performances. setState() déclenchera toujours un nouveau rendu à moins que la logique de rendu conditionnel ne soit implémentée dans shouldComponentUpdate().

Si des objets mutables sont utilisés et que la logique ne peut pas être implémentée dans shouldComponentUpdate(), appeler setState() uniquement lorsque le nouvel état diffère de l'état précédent évitera des rendus inutiles.

Il est toujours judicieux d'utiliser les API de la manière dont elles ont été conçues. Si les docs disent de ne pas muter votre état, alors vous feriez mieux de ne pas muter votre état.

Bien que setState() puisse être techniquement asynchrone, ce n'est certainement pas lent de façon notable. La fonction render() du composant sera appelée assez rapidement.

Un inconvénient de la définition directe de l'état est que les méthodes de cycle de vie de React - shouldComponentUpdate(), componentWillUpdate(), componentDidUpdate() - dépendent des transitions d'état appelées avec setState(). Si vous changez directement l'état et appelez setState() avec un objet vide, vous ne pouvez plus implémenter ces méthodes.

Un autre est que c'est juste un mauvais style de programmation. Vous faites en deux déclarations ce que vous pourriez faire en une seule.

De plus, il n'y a aucun avantage réel ici. Dans les deux cas, render() ne sera déclenché qu'après l'appel de setState() (ou forceUpdate()).

Vous prétendez avoir besoin de le faire sans vraiment expliquer ce qu'est ce besoin. Vous aimeriez peut-être détailler un peu plus votre problème. Il y a probablement une meilleure solution.

Il vaut mieux travailler avec le framework plutôt que contre.

MISE À JOUR

D'après les commentaires ci-dessous:

Le besoin est que je veux utiliser le hasSubmit modifié ci-dessous.

OK je comprends maintenant. Si vous devez utiliser immédiatement la future propriété d'état, votre meilleur pari est simplement de la stocker dans une variable locale.

const hasSubmit = false;

this.setState({
  hasSubmit: hasSubmit
});

if (hasSubmit) { 
  // Code that will use `hasSubmit` ...
51
David L. Walsh 9 mars 2016 à 03:19

Si vous souhaitez modifier l'état et déclencher un nouveau rendu en réagissant: Utilisez le deuxième code.

  this.setState({
    hasSubmit: false,
  });

Problèmes / erreurs avec le premier code:

  this.state.hasSubmit = false      // Updates state directly: 
                                    // You are not supposed to do this
                                    // except in ES6 constructors
  this.setState({})                 // passes an empty state to react.
                                    // Triggers re-render without mutating state
5
wintvelt 18 févr. 2019 à 07:02

Vous devez utiliser this.forceUpdate() dans le premier exemple pour forcer la mise à jour de l'état. Par exemple:

this.state.hasSubmit = false;
this.forceUpdate();

Mais il vaut mieux utiliser this.setState car c'est le mécanisme natif de vérification de l'état du moteur React qui est mieux que forcer la mise à jour.

Si vous mettez à jour un paramètre de this.state directement sans setState réagir, le mécanisme de rendu ne saura pas que certains paramètres d'état sont mis à jour.

1
Dmitriy 8 mars 2016 à 12:17

this.setState maintient le cycle de vie du composant React et ne ressemble pas à des variables de mutation (même si en interne il mute l'état). Ainsi, le flux à sens unique dans le cycle de réaction est maintenu sans aucun effet secondaire.

La mise en garde est que l'utilisation de this.setState ne fonctionne pas avec les constructeurs des classes ES6. Nous devons utiliser le modèle this.state = plutôt que this.setState dans les constructeurs ES6

4
Aditya Singh 8 mars 2016 à 14:58

Vous ne devez jamais ignorer les conseils de documentation. Au moment de l'écriture, setState autorise le deuxième argument qui est une fonction de rappel lorsque setState et le rendu sont terminés. Puisque vous ne nous indiquez jamais comment votre code va utiliser la valeur hasSubmit, je pense que d'autres peuvent trouver cela utile lorsqu'ils veulent s'assurer que le hasSubmit a été modifié.

4
Sany Liew 1 sept. 2016 à 03:17