Composants de présentation et de conteneur

Bismuth

Mise à jour de 2019: J’ai écrit cet article il y a longtemps et mes opinions ont depuis évolué. En particulier, je ne suggère plus de diviser vos composants comme ça. Si vous le trouvez naturel dans votre base de code, ce modèle peut être pratique. Mais je l’ai vu appliqué sans aucune nécessité et avec une ferveur presque dogmatique beaucoup trop de fois. La principale raison pour laquelle je l’ai trouvé utile était qu’il me permettait de séparer la logique à état complexe des autres aspects du composant. Les crochets me permettent de faire la même chose sans division arbitraire. Ce texte est laissé intact pour des raisons historiques mais ne le prenez pas trop au sérieux.

Il existe un modèle simple que je trouve extrêmement utile lors de l’écriture d’applications React. Si vous faites React depuis un moment, vous l’avez probablement déjà découvert. Cet article l’explique bien, mais je veux ajouter quelques points supplémentaires.

Vous trouverez vos composants beaucoup plus faciles à réutiliser et à raisonner si vous les divisez en deux catégories. Je les appelle des composants Contenant et de Présentation *, mais j’ai aussi entendu du Gras et du Maigre, du Intelligent et du Muet, de l’État et de la Pureté, des Écrans et des Composants, etc. Tous ne sont pas exactement les mêmes, mais l’idée de base est similaire.

Mes composants de présentation:

  • Sont préoccupés par l’apparence des choses.
  • Peut contenir à la fois des composants de présentation et des composants de conteneur ** à l’intérieur, et ont généralement un balisage DOM et des styles qui leur sont propres.
  • Permettent souvent le confinement par ce biais.accessoires.enfant.
  • N’ont aucune dépendance sur le reste de l’application, telles que les actions de flux ou les magasins.
  • Ne spécifiez pas comment les données sont chargées ou mutées.
  • Recevez des données et des rappels exclusivement via des accessoires.
  • Ont rarement leur propre état (quand ils le font, c’est l’état de l’interface utilisateur plutôt que les données).
  • Sont écrits en tant que composants fonctionnels, sauf s’ils ont besoin d’optimisations d’état, de hooks de cycle de vie ou de performances.
  • Exemples: Page, Barre latérale, Histoire, Informations utilisateur, Liste.

Composants de mon conteneur:

  • Sont préoccupés par la façon dont les choses fonctionnent.
  • Peut contenir à la fois des composants de présentation et des composants de conteneur ** à l’intérieur, mais n’ont généralement pas de balisage DOM, à l’exception de certaines divs d’emballage, et n’ont jamais de styles.
  • Fournissez les données et le comportement aux composants de présentation ou autres composants du conteneur.
  • Appelez les actions de flux et fournissez-les comme rappels aux composants de présentation.
  • Sont souvent avec état, car ils ont tendance à servir de sources de données.
  • Sont généralement générés à l’aide de composants d’ordre supérieur tels que connect() de React Redux, createContainer() de Relay ou Container.create() à partir d’Utils de flux, plutôt que écrits à la main.
  • Exemples : Page utilisateur, Barre d’abonnés, StoryContainer, Liste d’utilisateurs suivis.

Je les mets dans différents dossiers pour clarifier cette distinction.

Avantages de cette approche

  • Meilleure séparation des préoccupations. Vous comprenez mieux votre application et votre interface utilisateur en écrivant des composants de cette façon.
  • Meilleure réutilisabilité. Vous pouvez utiliser le même composant de présentation avec des sources d’état complètement différentes et les transformer en composants de conteneur séparés qui peuvent être réutilisés.
  • Les composants de présentation sont essentiellement la “palette” de votre application. Vous pouvez les mettre sur une seule page et laisser le concepteur modifier toutes leurs variations sans toucher à la logique de l’application. Vous pouvez exécuter des tests de régression de capture d’écran sur cette page.
  • Cela vous oblige à extraire des “composants de mise en page” tels que la barre latérale, la Page, le menu contextuel et à les utiliser.accessoires.enfants au lieu de dupliquer le même balisage et la même mise en page dans plusieurs composants de conteneur.

N’oubliez pas que les composants n’ont pas à émettre de DOM. Ils ont seulement besoin de fournir des limites de composition entre les préoccupations de l’interface utilisateur.

Profitez-en.

Quand introduire des conteneurs?

Je vous suggère de commencer d’abord à créer votre application avec uniquement des composants de présentation. Finalement, vous vous rendrez compte que vous passez trop d’accessoires dans les composants intermédiaires. Lorsque vous remarquez que certains composants n’utilisent pas les accessoires qu’ils reçoivent mais les transmettent simplement et que vous devez recâbler tous ces composants intermédiaires chaque fois que les enfants ont besoin de plus de données, c’est le bon moment pour introduire certains composants de conteneur. De cette façon, vous pouvez obtenir les données et les accessoires de comportement des composants de la feuille sans surcharger les composants non liés au milieu de l’arbre.

Il s’agit d’un processus continu de refactorisation, alors n’essayez pas de bien faire les choses la première fois. En expérimentant ce modèle, vous développerez un sens intuitif du moment où il est temps d’extraire certains conteneurs, tout comme vous savez quand il est temps d’extraire une fonction. Ma série gratuite Redux Egghead pourrait vous aider avec cela aussi!

Autres dichotomies

Il est important que vous compreniez que la distinction entre les composants de présentation et les conteneurs n’est pas technique. C’est plutôt une distinction dans leur but.

En revanche, en voici quelques apparentés (mais différents !) distinctions techniques:

  • Avec État et sans État. Certains composants utilisent la méthode React setState() et d’autres non. Alors que les composants de conteneur ont tendance à être avec état et que les composants de présentation ont tendance à être sans état, ce n’est pas une règle difficile. Les composants de présentation peuvent être avec état, et les conteneurs peuvent également être sans état.
  • Classes et fonctions. Depuis React 0.14, les composants peuvent être déclarés à la fois en tant que classes et en tant que fonctions. Les composants fonctionnels sont plus simples à définir, mais il leur manque certaines fonctionnalités actuellement disponibles uniquement pour les composants de classe. Certaines de ces restrictions pourraient disparaître à l’avenir, mais elles existent aujourd’hui. Parce que les composants fonctionnels sont plus faciles à comprendre, je vous suggère de les utiliser sauf si vous avez besoin d’optimisations d’état, de hooks de cycle de vie ou de performances, qui ne sont disponibles que pour les composants de classe pour le moment.
  • Pur et Impur. Les gens disent qu’un composant est pur s’il est garanti de retourner le même résultat avec les mêmes accessoires et les mêmes états. Les composants purs peuvent être définis à la fois comme des classes et des fonctions, et peuvent être à la fois avec état et sans état. Un autre aspect important des composants purs est qu’ils ne dépendent pas de mutations profondes dans les props ou l’état, de sorte que leurs performances de rendu peuvent être optimisées par une comparaison superficielle dans leur hook shouldComponentUpdate(). Actuellement, seules les classes peuvent définir shouldComponentUpdate() mais cela pourrait changer à l’avenir.

Les composants de présentation et les conteneurs peuvent tomber dans l’un ou l’autre de ces seaux. D’après mon expérience, les composants de présentation ont tendance à être des fonctions pures sans état et les conteneurs ont tendance à être des classes pures à état. Cependant, ce n’est pas une règle mais une observation, et j’ai vu les cas exactement opposés qui avaient du sens dans des circonstances spécifiques.

Ne prenez pas la séparation des composants de présentation et de conteneur comme un dogme. Parfois, cela n’a pas d’importance ou il est difficile de tracer la ligne. Si vous ne savez pas si un composant spécifique doit être présenté ou un conteneur, il est peut-être trop tôt pour décider. Ne transpire pas !

Exemple

Cet essentiel de Michael Chan le cloue à peu près.

Pour en savoir plus

  • Mise en route avec Redux
  • Les Mixins sont morts, Vive la composition
  • Composants de conteneurs
  • Conception Web atomique
  • Construction du Fil d’actualités Facebook avec Relais

Notes de Bas de Page

* Dans une version antérieure de cet article, je les appelais des composants “intelligents” et “stupides”, mais cela était trop dur pour les composants de présentation et, surtout, n’expliquait pas vraiment la différence dans leur but. J’apprécie beaucoup mieux les nouveaux termes, et j’espère que vous aussi!

** Dans une version antérieure de cet article, j’ai affirmé que les composants de présentation ne devraient contenir que d’autres composants de présentation. Je ne pense plus que ce soit le cas. Qu’un composant soit un composant de présentation ou un conteneur est son détail d’implémentation. Vous devriez pouvoir remplacer un composant de présentation par un conteneur sans modifier aucun des sites d’appel. Par conséquent, les composants de présentation et de conteneur peuvent contenir d’autres composants de présentation ou de conteneur très bien.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.