Les containers depuis les Hooks

React & Composants Partie I

Olivier YOUF
Just-Tech-IT
5 min readMay 4, 2020

--

Aussi bien notre ami Dan Abramov que son homologue Kent C. Dodds, ont indiqué que pour eux les containers n’avaient plus lieu d’être. Par ailleurs, la documentation n’a jamais mentionné cette séparation. Nous allons voir ce qu’est le “Separation of concerns” puis comment et pourquoi je l’adapte quand même à mes projets d’aujourd’hui.

Dumb & Dumber

Depuis que j’ai commencé à faire du React, on m’a souvent répété que la vue devait être séparée de la logique. Mais quel est la fondation de ce principe ? En voici une réponse rapide à travers une brève description.

Composant :

  • Do one thing : Son but est de s’occuper uniquement de la présentation.
  • Il est pur : quelque soit le moment et le nombre d’appels, nous sommes certain qu’il sera toujours identique. Il est uniquement dépendant des paramètres.
  • Il est stateless : il ne contient pas d’état, cela est important pour conserver son état pur.
  • Il est fonctionnel : Etant donné qu’il est pur et stateless, il peut être représenté par une simple fonction composant. Il devient très léger et beaucoup plus lisible.
  • Il est indépendant : il peut afficher d’autre composant, mais ne va pas nécessiter d’import particulier de service, de flux ou autre. Il peut être déplacé ou que ce soit dans l’application.

Container :

  • Son but est de lier l’intelligence au composant.
  • Il peut appeler les services, les API, le contexte, Redux etc.
  • Il peut enrichir les composants avec des HOC
  • Il peut contenir un état.

Le principe est vraiment de séparer la vue de la logique. Cela a beaucoup d’avantages :

  • Les vues pures permettent un développement et des tests facilités grâce à des données transmises via les propriétés. On pourra également utiliser une même vue avec des logique différentes.
  • Une vue pure fera facilement partie d’une palette de composants (dans un storybook par exemple). Par ailleurs cela peut s’apparenter à du TDD.
  • Une lisibilité accrue. En regardant la vue on se concentre uniquement sur son affichage, en regardant le container on se concentre sur la logique.

Mille tonnerres, Mouche !

Photo by Vishal Jadhav on Unsplash

Avec l’arrivée des Hooks, Dan et Kent se sont penchés sur le sujet en début d’année dernière (c’est à dire à la sortie officielle de la version 16.8). Dan a mis a jour son article sur le pattern en indiquant qu’il ne le trouvait plus approprié et Kent a clairement abondé dans son sens dans sa séance d’AMA (les deux liens en annexes).

Les raisons sont les suivantes :

  • Les Hooks sont facilement lisibles et compréhensibles. Effectivement ils permettent d’évier les HOC (avec recompose par exemple) et / ou les render props imbriquées.
  • Les containers permettent d’extraire la logique du composant. Les hooks font de même, donc aucune raison de séparer également dans un container. On peut, au besoin, extraire les hooks dans un custom hook.

L’exemple simple de Kent serait de cette forme :

C’est facilement lisible et on voit que l’on a su exporter le hook useCounter. Cependant l’exemple est simpliste et souvent nous avons des composants bien plus complexes a gérer.

Grandir ? Moi Jamais !

Kent C Dodds indique dans sa vidéo n’avoir jamais vu la plus value des containers. Et c’est parce que chez nous, nous en voyons beaucoup que je reste intimement convaincu que ce pattern a son importance.

Première étape

Les exemples donnés sont toujours simples. Je pense que pour un petit composant (comme pour l’exemple) le principe peut s’appliquer. Cependant dans nos projets, régulièrement nous nous confrontons à des principes et des besoins logiques plus complexes, et de ce fait nous nous retrouvons avec des composants et logiques plus grands.

Voyons ça sur un exemple (un peu) plus complexe. (Tiré de mon codesandbox utilisé lors de ma conférence Devoxx sur les hooks). Ne nous attardons pas trop sur le code mais plus sur l’aspect général.

Ici nous avons beaucoup de code. La lisibilité n’est pas évidente.

On pourrait séparer et mettre dans un custom Hook.

Puis l’intégrer dans le composant :

A ce stade, nous nous retrouvons avec un composant bien plus lisible.

Deuxième étape

On pourrait s’arrêter là. Dans des cas simples, et pour bon nombre d’entre vous cela peut tout à fait être le cas. Cependant certains principes que je trouve toujours d’actualité, se retrouvent en défaut :

  • La vue pure: Ici même si on a séparé la logique dans le custom Hook, la vue n’est pas pure car la logique est quand même fortement couplée.
  • Le découplage: de ce couplage fort, impossible de soustraire la logique. Il devient plus complexe par exemple de faire un storybook. (Je vous invite à lire l’article d’Eric Elliott à ce sujet)
  • Le TDD : afin de tester correctement la vue, on ne peut pas simuler la logique, sauf en mockant le hook. Ce qui pour moi est un code smell.

C’est ici que va intervenir le container. Il va permettre de séparer la vue complexe de l’ensemble des hooks et la logique. On aura donc une séparation telle que :

  • Une vue : via une fonction pure. Facilement lisible, testable et modifiable
  • La logique : des hooks et des fonctions purs. Egalement facilement testables, sans couplage avec l’extérieur.
  • Un container : Ce dernier servira de ciment entre la logique et la vue. Il injectera les dépendances avec les services, les API et servira de template de composants.

Dans notre example, Tout en gardant le même fichier de hooks, on ajoute le container :

puis un composant :

Voici le codesandbox contenant tous les exemples.

Tester c’est douter

Avec cette organisation, nous testerons :

Dans un prochain article je vous montrerai comment avec cette organisation nous pouvons tester à 100% un composant complet (sans se forcer). Nous partirons d’un fork de celui ci dessus.

Tous les chemins mènent à Rome

Nous avons donc vu comment organiser proprement son code. Ce n’est bien évidemment pas la seule manière de faire, c’est une manière de faire. Grand nombre de développeurs vont simplifier, réduire le nombre de fichiers. La plupart auront raison, car ils auront leur façon de faire qui leur convient. Ca sera dans la majorité des cas partagé avec les membres de leur équipe.

La meilleure façon de faire les choses est celle définie collégialement avec son équipe.

📙 Ressources

Kent C Dodds lors de son AMA

Retrouvez également mon précédent article sur le blog Axa :

--

--

Olivier YOUF
Just-Tech-IT

I am a FrontEnd developer. My speciality is React JS but I am sensitive to all. I love running, especially in mountains.