Passer l'état du magasin en tant qu'accessoires, ou chaque composant accédant aux magasins globaux?

Je suis un peu confus par les instructions: "rend l'application entière" et "passer l'État aux composants enfants".

Exemple 1:

J'ai un todos application avec un AppComponent et TodosListComponent. Le AppComponent saisit le tableau de todos du magasin et le transmet en tant que propriété au TodosListComponent.

Exemple 2:

J'ai une énorme application avec beaucoup d'état. J'ai comme 50 composants qui construisent mon application. Est-ce que je veux passer tout l'état des magasins de {[0] } à travers tous les 50 les composants?

Je me demande donc quelle est la convention? Il est plus logique pour moi de laisser les composants individuels écouter directement les magasins dont ils se soucient. L'avantage, c'est que seuls les composants individuels rerender, mais pourquoi alors le concept de "l'ensemble de l'application rerender sur changement d'état"?

Quels sont les avantages et les inconvénients de chacun? Quelle est la convention commune?

24
demandé sur FakeRainBrigand 2014-10-25 19:18:48

2 réponses

Il y a plusieurs façons de gérer cela. Je pense qu'ils sont tous valides et ont leurs propres compromis.

Obtenez tout l'état et transmettez-en des morceaux aux enfants

C'est la technique que vous avez spécifiquement posée. En utilisant cette méthode, vous aurez une fonction ou une méthode disponible pour votre composant de niveau supérieur qui transforme toutes les données des magasins en un "grand sac d'état", puis vous passerez sélectivement des morceaux de ces données aux composants enfants. Si ces composants ont leur leurs propres enfants, ils le transmettront au besoin.

L'avantage de cette méthode est qu'elle rend les choses généralement facile à déboguer. Si vous devez changer la façon dont un morceau d'état est récupéré à partir d'un magasin, vous n'avez qu'à le changer dans le composant de niveau supérieur-tant qu'il est transmis avec le même nom, les autres composants "fonctionneront juste."Si certaines données sont fausses, vous devriez seulement avoir besoin de regarder au même endroit pour comprendre pourquoi.

L'inconvénient de cette technique ce que je appelez "props explosion"- vous pouvez finir par passer un lot de propriétés autour. J'utilise cette méthode dans une application de flux de taille moyenne, et un extrait du composant d'application de niveau supérieur ressemble à ceci:

<section id="col-left">
  <Filters loading={this.state.loading}
            events={this.state.events}
            playbackRate={this.state.videoPlayback.playbackRate}
            autoPlayAudio={this.state.audioPlayback.autoPlay}
            role={this.state.role} />
</section>

<section id="col-center" className={leftPaneActive ? "" : "inactive"}>
  <SessionVideo videoUuid={this.state.session.recording_uuid}
                lowQualityVideo={this.state.session.low_quality_video_exists}
                playbackRate={this.state.videoPlayback.playbackRate} />
  <section id="transcript">
    <Transcript loading={this.state.loading}
                events={this.state.events}
                currentEvents={this.state.currentEvents}
                selection={this.state.selection}
                users={this.state.session.enrolled_users}
                confirmedHcs={this.state.ui.confirmedHcs}

                currentTime={this.state.videoPlayback.position}
                playing={this.state.videoPlayback.playing} />
  </section>
</section>

En particulier, il peut y avoir beaucoup de composants entre le niveau supérieur et un enfant éventuel qui ne font rien avec les données sauf les transmettre, couplant plus étroitement ces composants à leur position dans la hiérarchie.

Dans l'ensemble, j'aime le débogage cette technique fournit, bien que l'application soit devenue plus grande et plus complexe, j'ai trouvé que ce n'était pas l'idée de le faire avec un seul composant de niveau supérieur.

Obtenez tout l'état et passez - le comme un objet

L'un des développeurs de Facebook a mentionné cette technique. Ici, vous obtiendrez un gros sac d'état, comme ci-dessus, mais vous passerez le tout (ou des sous-sections entières) plutôt que des propriétés individuelles. En utilisant React.PropTypes.shape dans les composants enfants, vous pouvez assurez-vous que les bonnes propriétés sont transmises.

L'avantage est que vous passez beaucoup moins de propriétés; l'exemple ci-dessus pourrait ressembler plus à ceci:

<section id="col-left">
  <Filters state={this.state} />
</section>

<section id="col-center" className={leftPaneActive ? "" : "inactive"}>
  <SessionVideo session={this.state.session}
                playback={this.state.videoPlayback} />
  <section id="transcript">
    <Transcript state={this.state} />
  </section>
</section>

L'inconvénient est qu'il devient un peu plus difficile de faire face aux changements dans la forme de l'état; plutôt que de simplement changer le composant de niveau supérieur, vous devrez traquer partout où cette donnée est utilisée et changer la façon dont ce composant accède à la propriété. En outre, shouldComponentUpdate peut potentiellement devenir un peu plus délicat à mettre en œuvre.

Permet aux composants d'obtenir leur propre état

À l'autre extrémité du spectre, vous pouvez accorder des composants enfants spécifiques à l'application (c'est-à-dire non réutilisables) pour accéder aux magasins et créer leur propre état en fonction des événements de modification du magasin. Les composants qui construisent leur propre état comme celui-ci sont parfois appelés "controller-views" ou, plus communément de nos jours, "container components."

L'avantage, bien sûr, est que vous n'avez pas à traiter avec des propriétés passantes (autres que les gestionnaires de changement et les propriétés pour des composants plus réutilisables).

L'inconvénient, cependant, est que vos composants sont plus fortement couplés aux magasins-changer les magasins ou les données qu'ils fournissent (ou l'interface via laquelle ils fournissent ces données) peut vous forcer à revoir le code pour un plus grand nombre de composants.

En outre, comme mentionné dans les commentaires, cela peut potentiellement rendre le rendu du serveur un peu plus difficile. Si vous n' utilisez les propriétés (surtout au niveau supérieur), vous pouvez les transporter plus facilement vers le client et réinitialiser React avec les mêmes propriétés. En permettant aux magasins de déterminer leurs propres données, vous devez en quelque sorte injecter ces données dans les magasins pour permettre aux composants d'obtenir ces données.

Une approche commune, et que j'utilise généralement maintenant, consiste à faire en sorte que chaque composant de votre application ne repose que sur des accessoires pour l'état global de l'application, puis décide s'il est plus logique de (1) Les connecter directement au flux en les enveloppant dans un conteneur, ou (2) permettre aux accessoires d'être transmis à partir d'un conteneur parent.


Il y a des abstractions que vous pourriez être en mesure d'utiliser pour rendre certaines de ces techniques plus viables. Par exemple, un dev Facebook avait ceci à dire dans un commentaire sur Hacker News :

Maintenant, toutes vos données sont dans les magasins, mais comment les introduire dans le composant spécifique qui en a besoin? Nous avons commencé avec de grands composants de haut niveau qui tirez toutes les données nécessaires pour leurs enfants, et le transmettre à travers les accessoires. Cela conduit à beaucoup de code cruft et non pertinent dans les composants intermédiaires. Ce que nous avons décidé, pour la plupart, ce sont les composants qui déclarent et récupèrent les données dont ils ont besoin eux-mêmes, à l'exception de quelques petits composants plus génériques. Comme la plupart de nos données sont récupérées de manière asynchrone et mises en cache, nous avons créé des mixins qui permettent de déclarer facilement les données dont votre composant a besoin, et d'accrocher la récupération et l'écoute mises à jour dans les méthodes de cycle de vie (componentWillMount, etc.).

34
répondu Michelle Tilley 2015-12-27 17:13:13

Jason Bonta de Facebook a expliqué le concept de "conteneurs" dans son React.js Conf 2015 parler.

Pour résumer: les conteneurs sont simplement des composants qui enveloppent d'autres composants, et prennent en charge toutes les préoccupations liées aux données telles que parler aux magasins, tandis que le composant sous-jacent se concentre uniquement sur la vue (balisage/styles/etc.) et ne se soucie pas d'où viennent les données.

Cela rend le composant

  • Hautement réutilisable car il peut être enveloppé avec un autre conteneur lorsque des données doivent provenir d'un endroit différent,

  • Ne contient pas d'état non pertinent, donc plus facile à implémenter et à optimiser shouldComponentUpdate, et

  • L'utilisation de la composition plutôt que des mixines pour cela s'aligne avec ce qui est probablement l'avenir de React avec ES6, qui n'a pas de mixines idiomatiques.

3
répondu Raman 2015-07-15 15:32:16