[DIY] State Management - React Vs. Vue đ
Les annĂ©es passent, les technologies Ă©voluent, et pourtant certains patterns de dĂ©veloppement restent intacts, voire se bonifient avec le temps⊠Câest le cas du State Management !
Introduit avec Flux, une architecture pensĂ©e par Facebook pour Facebook, le State Management est aujourdâhui un incontournable du dĂ©veloppement Web. Ce paradigme de dĂ©veloppement se caractĂ©rise principalement par son flux de donnĂ©es unidirectionnel ; en opposition Ă la liaison bidirectionnelle de donnĂ©es utilisĂ©e par les frameworks MVW tel quâAngularJS, ou plus rĂ©cemment Vue. Flux est crĂ©Ă© pour rĂ©soudre certains dĂ©fauts du pattern MVVM (Model-View / View-Model), notamment lors de la montĂ©e Ă lâĂ©chelle dâapplications Web. Avec la crĂ©ation du concept de âstoreâ, il nây a plus (ou en tout cas moins) de problĂšme liĂ© aux diffĂ©rentes sources de donnĂ©es. Tout est alors centralisĂ© au mĂȘme endroit. On dit que le store est unique source de vĂ©ritĂ© !
Tout comme les fonctions callbacks, les promesses ou encore les streams, le State Management est un paradigme de programmation ârĂ©activeâ. LâidĂ©e dâun tel dĂ©veloppement est que les composants utilisant les donnĂ©es du store, rĂ©agissent lorsque ces mĂȘmes donnĂ©es sont mises Ă jour. Pour cela, le State Management suit une certaine logique :
- Le store est en lecture seule
- Les donnĂ©es sont mises Ă jour par un âdispatcherâ
- Le dispatcher est sollicité par des actions
- Lâinterface utilisateur dĂ©clenche les actions
Selon les implĂ©mentations de Flux, la notion de âdispatcherâ est plus ou moins explicite, cependant le flux de donnĂ©es reste le mĂȘme : la vue dispatche les actions qui mettent Ă jour les donnĂ©es du store et implicitement mettent Ă jour les vues associĂ©es Ă ces donnĂ©es. Dans le monde du dĂ©veloppement Web, il existe beaucoup dâimplĂ©mentations diffĂ©rentes de Flux : Fluxxor, MobX, Overmind, etc⊠Redux et Vuex sont respectivement les plus connues pour les Ă©cosystĂšmes React et Vue.
Bien que ces dĂ©pendances soient extrĂȘmement pratiques et facilite grandement le travail du dĂ©veloppeur, il est possible de construire soit mĂȘme une architecture de State Management. Câest ce qui nous amĂšne Ă cet article !
Ci-dessous, nous allons voir comment coder son propre Redux / Vuex, Ă©tapes par Ă©tapes, en utilisant les derniĂšres versions des outils React et Vue actuellement disponibles (version 17 pour la librairie de Facebook, et version 3 pour le framework communautaire).
NB : React utilise les hooks, et Vue utilise lâAPI Composition. Ces derniĂšres fonctionnalitĂ©s Ă©tant trĂšs similaires, il va ĂȘtre intĂ©ressant de voir comment celles-ci sâinterfacent dans ce genre de dĂ©veloppement.
La mise en oeuvre dâun State Management (que ce soit en React ou en Vue) se divise en deux parties :
- Le Provider qui initialise la mécanique du store
- Les Consumers qui interagissent avec le store, en lecture et en âdispatchantâ les actions
Partie 1 - Le Provider
La crĂ©ation dâun store avec la librairie de Facebook sâeffectue grĂące Ă la combinaison astucieuse des hooks et de lâAPI Context. La crĂ©ation dâun contexte nous permet dâavoir accĂšs au composant <Provider />
qui se chargera dâintĂ©grer les donnĂ©es du store fournies par le hook useReducer()
. En effet, le pattern de dĂ©veloppement âState - Reducerâ occupe une place importante dans la gestion dâun Ă©tat complexe dâun composant.
Ces quelques lignes suffisent Ă instaurer une mĂ©canique de store. Cependant, afin de rĂ©pandre les donnĂ©es (issues dâun contexte) aux composants enfants, il faut encore encapsuler ces mĂȘmes composants par le composant parent (<StateProvider />
), de prĂ©fĂ©rence au plus haut niveau de lâapplication.
Pour ce qui est du framework communautaire, grĂące Ă la version 3 de Vue, lâinitialisation du store repose majoritairement sur lâAPI Composition, ainsi que sur le pattern de dĂ©veloppement âProvide / Injectâ. Cette derniĂšre fonctionnalitĂ© (dĂ©jĂ prĂ©sente dans Vue 2) est trĂšs similaire Ă lâAPI Context de React, et permet dâĂ©tendre des donnĂ©es globales Ă toute une partie de lâapplication.
Ci-dessus (les fonctions Ă©tant relativement explicites) on sâaperçoit rapidement que lâon dĂ©clare une variable rĂ©active (lâĂ©tat global de lâapplication), puis on la rend disponible, ainsi que les fonctions permettant de la faire muter. Ensuite (et tout comme React), il ne suffit pas dâinjecter les donnĂ©es du store dans les composants enfants pour interagir avec ce dernier, il faut Ă©galement âwrapperâ ces mĂȘmes composants par le composant parent (<StateProvider />
Ă nouveau), responsable du store.
Partie 2 - Le Consumer
NB : Dans la suite de cet article, les classes CSS que vous retrouverez dans le rendu des composants <StateConsumer />
sont issues dâun framework UI : Bulma !
Une fois le composant enfant encapsulé par le composant garant du store, on récupÚre ses données grùce à la fonction inject()
avec le framework Vue. Le paramĂštre de cette fonction nâest autre quâun identifiant unique, qui rĂ©fĂšre Ă la variable / la fonction fourni(e) prĂ©alablement par le composant parent.
Lâoption setup()
va donc transmettre lâĂ©tat du store, ainsi que les fonctions permettant de le mettre Ă jour, au composant fils <StateConsumer />
avant de monter ce dernier. Dans le template ci-dessus, on utilise directement la valeur state.fullName
du store, et on la met Ă jour soit lorsque lâĂ©vĂ©nement onchange
est dĂ©clenchĂ© par lâ<input>
, soit lorsque lâĂ©vĂ©nement onclick
est joué par le <button>
.
Du cÎté de la libraire React, la récupération des valeurs du store (à savoir son état, ainsi que la fonction dispatch()
) sâeffectue au travers dâun autre hook : useContext()
. En important le contexte du store, et en le passant en paramĂštre de cette fonction, un composant âstatelessâ se âconnectâ (rĂ©fĂ©rence Ă Redux) au store de lâapplication.
Reste encore à mettre à jour le store⊠Pour cela, il suffit de dispatcher une action. Par convention, une action est un objet disposant de deux propriétés :
- Le âtypeâ servant de rĂ©fĂ©rence au dispatcher
- Le âpayloadâ sur lequel le store sâappuie pour mettre Ă jour son Ă©tat
Hooks Vs. API Composition
Lâintroduction des hooks avec React 16.8 et lâapparition de lâAPI Composition de Vue 3, modifient notre façon dâutiliser le store. DĂ©jĂ prĂ©sente depuis la version 7.1.0 de la dĂ©pendance âReact-Reduxâ, les hooks (useSelector()
/ useDispatch()
) facilitent grandement la âconnexionâ avec le store, et Ă©vitent une dĂ©marche de HOC (High Order Component), pour passer certaines donnĂ©es dâun composant parent, vers les propriĂ©tĂ©s dâun composant enfant. LâAPI Composition de Vue, peut-ĂȘtre utilisĂ© de maniĂšre trĂšs similaire aux hooks de React.
Cette maniĂšre de faire est de plus en plus rĂ©pandue dans les dĂ©veloppements Web, et rĂ©pond au principe suivant : dĂ©couper pour mieux rĂ©gner ; Parfait pour les applications comptant plus de 100 composantsâŠ
NB : La convention veut que le nom de ce genre de fonction dĂ©bute par âuseâ pour prĂ©ciser quâil sâagit dâune fonction de composition / dâun hook personnalisĂ©.
Ce concept est plutĂŽt intelligent, et permet de penser nos applications plus finement, brique par brique. Cela favorise ainsi la rĂ©usabilitĂ© du code pour les composants ayant la mĂȘme logique : la mĂȘme façon de lire le store et / ou de mettre Ă jour tout ou partie du store.
NB : Lâavantage de la fonction ci-dessus, est quâelle gĂšre directement la valeur par dĂ©faut du âfieldâ si la valeur de ce dernier nâest pas (encore) prĂ©sente dans le store ; plutĂŽt quâune gestion dans le template du composant.
Conclusion
Jâutilise le State Management depuis plusieurs annĂ©es maintenant, souvent avec Redux (en parallĂšle avec Vuex), jâai appris Ă connaĂźtre son fonctionnement et ses nombreux avantages.
Bien quâextrĂȘmement pratique, le State Management prend tout son sens dans une application Web Ă lâĂ©chelle, avec une multitude de composants, ainsi que de multiples fonctionnalitĂ©s. La centralisation des donnĂ©es, leur lecture et leurs mises Ă jour deviennent alors plus aisĂ©es.
Les derniĂšres versions des frameworks / librairies JavaScript nous amĂšne Ă dĂ©composer plus finement nos applications. Lâusage des hooks / de lâAPI Composition rend le State Management plus accessible et clair (plus besoin de dĂ©pendances supplĂ©mentaires mystifiant une partie du code). Il mâarrive donc aujourdâhui dâutiliser cette logique de dĂ©veloppement Ă plus petite Ă©chelle (pour construire des Single Page Apps avec moins de 50 composants par exemple).
Vous lâaurez compris, je suis assez fan de la programmation rĂ©active par lâusage dâun store. Si vous dĂ©veloppez rĂ©guliĂšrement avec Redux (ou Vuex), ou mĂȘme dâautres librairies (RxJS), je vous invite Ă faire cet exercice de crĂ©ation dâun State Management from scratch (pour le plaisir du code đ).
Finalement, cette comparaison entre React et Vue, permet de se rendre compte que ces deux frameworks gravitant autour dâun DOM Virtuel ne sont pas aussi Ă©loignĂ©s lâun de lâautre, malgrĂ© des concepts qui leurs sont propres (tel que la paire âProvide / Injectâ de Vue). Ă la suite de cet article, je pense rĂ©itĂ©rĂ© ce travail sur dâautres outils, surement Svelte dont certaines notions sont assez proches de React et Vue. Cela donnera probablement suite Ă un article dĂ©rivĂ©âŠ
Sources
Dans le cadre de cet article, jâai rĂ©alisĂ© deux projets de dĂ©monstration (visuellement identiques) en appliquant lâarchitecture explicitĂ© prĂ©cĂ©demment. Voici les liens :