Les meilleurs outils de gestion d'état de réaction pour les applications d'entreprise

Publié: 2022-03-11

Les développeurs d'applications React au niveau de l'entreprise savent à quel point la gestion des états est cruciale pour une expérience utilisateur cohérente.

Cependant, l'utilisateur n'est pas le seul concerné par la gestion de l'état. Les développeurs de React créent et maintiennent l'état. Ils veulent que la gestion des états soit simple, extensible et atomique. React a évolué dans cette direction en introduisant des crochets.

Des problèmes peuvent survenir lorsque l'état doit être partagé entre plusieurs composants. Les ingénieurs doivent trouver des outils et des bibliothèques qui répondent à leurs besoins, tout en répondant aux normes élevées requises pour les applications de niveau entreprise.

Dans cet article, j'analyserai et comparerai les bibliothèques les plus populaires et choisirai la plus appropriée pour la gestion d'état dans une application au niveau de l'entreprise.

Capacités de gestion de l'état de réaction intégrées

React dispose d'un excellent outil pour fournir des données sur plusieurs composants. L'objectif principal de Context est d'éviter le prop-drilling. Notre objectif est d'obtenir un outil facile à utiliser pour gérer l'état dans divers scénarios susceptibles d'être rencontrés dans les applications d'entreprise : mises à jour fréquentes, refontes, introduction de nouvelles fonctionnalités, etc.

Bien que tout cela soit théoriquement faisable avec Context, cela nécessiterait une solution personnalisée qui nécessite du temps pour être configurée, prise en charge et optimisée. Le seul avantage de Context est qu'il ne dépend pas d'une bibliothèque tierce, mais cela ne peut pas l'emporter sur l'effort de maintenir cette approche.

De plus, Sebastian Markbage, membre de l'équipe React, a mentionné que la nouvelle API Context n'a pas été conçue et optimisée pour les mises à jour à haute fréquence, mais plutôt pour les mises à jour à basse fréquence comme les mises à jour de thème et la gestion de l'authentification.

Examen des bibliothèques existantes

Il existe des dizaines d'outils de gestion d'état sur GitHub (par exemple, Redux, MobX, Akita, Recoil et Zustand). Cependant, prendre chacun d'eux en considération conduirait à des recherches et des comparaisons sans fin. C'est pourquoi j'ai réduit ma sélection aux trois principaux concurrents en fonction de leur popularité , de leur utilisation et de leur maintenance .

Pour rendre la comparaison explicite, j'utiliserai les attributs de qualité suivants :

  • Convivialité
  • Maintenabilité
  • Performance
  • Testabilité
  • Évolutivité (fonctionne avec les mêmes performances sur les états les plus grands)
  • Modifiable
  • Réutilisabilité
  • Écosystème (dispose d'une variété d'outils d'assistance pour étendre la fonctionnalité)
  • Communauté (a beaucoup d'utilisateurs et leurs questions sont répondues sur le Web)
  • Portabilité (peut être utilisé avec des bibliothèques/frameworks autres que React)

Redux

Redux est un conteneur d'état créé en 2015. Il est devenu très populaire car :

  • Il n'y avait pas d'alternative sérieuse lors de son lancement.
  • Il a fourni une séparation entre l'état et les actions.
  • La magie react-redux a permis une connexion d'état simple.
  • Le co-créateur de la bibliothèque est le célèbre développeur Facebook et membre de l'équipe principale de React, Dan Abramov.

Animation montrant la progression des états et des actions depuis et vers le réducteur, en utilisant Redux.

Vous disposez d'un magasin mondial où résident vos données. Chaque fois que vous devez mettre à jour le magasin, vous envoyez une action qui va au reducer . Selon le type d'action, le réducteur met à jour l'état de manière immuable.

Pour utiliser Redux avec React, vous devrez abonner les composants aux mises à jour du magasin via react-redux .

Exemple d'API Redux

Les parties fondamentales de Redux dans la base de code qui le différencie des autres outils sont les tranches. Ils contiennent toute la logique des actions et des réducteurs.

CodeSandbox

 // slices/counter.js import { createSlice } from "@reduxjs/toolkit"; export const slice = createSlice({ name: "counter", initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1; }, decrement: (state) => { state.value -= 1; } } }); export const actions = slice.actions; export const reducer = slice.reducer; // store.js import { configureStore } from "@reduxjs/toolkit"; import { reducer as counterReducer } from "./slices/counter"; export default configureStore({ reducer: { counter: counterReducer } }); // index.js import React from 'react' import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import App from './App' import store from './store' ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) // App.js import React from "react"; import { useSelector, useDispatch } from "react-redux"; import { actions } from "./slices/counter"; const App = () => { const count = useSelector((state) => state.counter.value); const dispatch = useDispatch(); return ( <div> <div> <button onClick={() => dispatch(actions.increment())}>Increment</button> <span>{count}</span> <button onClick={() => dispatch(actions.decrement())}>Decrement</button> </div> </div> ); }; export default App;

Attributs de qualité

  • Convivialité . Redux est devenu très simple avec l'introduction du package officiel de la boîte à outils. Vous créez une tranche (une combinaison de l'état initial, des réducteurs et des actions), la transmettez au magasin et y accédez dans un composant via des crochets.
  • Maintenabilité . Redux est simple. Il ne nécessite pas de connaissances approfondies pour comprendre comment améliorer ou réparer quelque chose.
  • Performances . Le principal influenceur de performance avec Redux est l'ingénieur logiciel. Redux est un outil simple sans trop de logique. Si vous constatez que les mises à jour d'état sont lentes, vous pouvez suivre les directives officielles pour les accélérer.
  • Testabilité . Redux se compose de fonctions pures (actions et réducteurs), ce qui le rend idéal pour les tests unitaires. Il fournit également le mécanisme pour écrire des tests d'intégration où le magasin, les actions et les réducteurs fonctionnent ensemble.
  • Évolutivité . Par défaut, Redux a un état global, ce qui le rend difficile à mettre à l'échelle. Cependant, il existe une bibliothèque redux-dynamic-modules qui permet la création de réducteurs modulaires et d'intergiciels.
  • Modifiable . La personnalisation de Redux est une affaire sans effort car il prend en charge le middleware.
  • Réutilisabilité . Redux est indépendant du framework, il est donc très bon pour la réutilisation.
  • Écosystème . Redux offre un écosystème géant de modules complémentaires, de bibliothèques et d'outils utiles.
  • Communauté . Redux, la plus ancienne bibliothèque de gestion d'état de notre comparaison, a rassemblé une grande communauté avec une base de connaissances importante. Il y a environ 30 000 questions (~ 19 000 réponses) avec une balise redux sur Stack Overflow.
  • Pouls . Redux est mis à jour et maintenu régulièrement.

MobX

MobX est une autre bibliothèque relativement ancienne avec 23 000 étoiles sur GitHub. Ce qui le distingue de Redux, c'est qu'il suit le paradigme OOP et utilise des observables. MobX a été créé par Michel Weststrate et est actuellement maintenu par un groupe de passionnés de l'open source avec l'aide de Mendix, basé à Boston.

Diagramme illustrant la gestion des états à l'aide de MobX, des actions aux effets secondaires en passant par les états observables et les valeurs calculées.

Dans MobX, vous créez une classe JavaScript avec un appel makeObservable à l'intérieur du constructeur qui est votre magasin observable (vous pouvez utiliser le décorateur @observable si vous avez le chargeur approprié). Ensuite, vous déclarez les propriétés (état) et les méthodes ( actions et valeurs calculées ) de la classe. Les composants s'abonnent à ce magasin observable pour accéder à l'état, aux valeurs calculées et aux actions.

Une autre caractéristique essentielle de MobX est la mutabilité. Il permet de mettre à jour l'état en silence au cas où vous voudriez éviter les effets secondaires.

Exemple d'API MobX

Une caractéristique unique de MobX est que vous créez des classes ES6 presque pures avec toute la magie cachée sous le capot. Il nécessite moins de code spécifique à la bibliothèque pour garder la concentration sur la logique.

CodeSandbox

 // stores/counter.js import { makeAutoObservable } from "mobx"; class CounterStore { value = 0; constructor() { makeAutoObservable(this); } increment() { this.value += 1; } decrement() { this.value -= 1; } } export default CounterStore; // index.js import React from "react"; import ReactDOM from "react-dom"; import { Provider } from "mobx-react"; import App from "./App"; import CounterStore from "./stores/counter"; ReactDOM.render( <Provider counter={new CounterStore()}> <App /> </Provider>, document.getElementById("root") ); // App.js import React from "react"; import { inject, observer } from "mobx-react"; const App = inject((stores) => ({ counter: stores.counter }))( observer(({ counter }) => { return ( <div> <div> <button onClick={() => counter.increment()}>Increment</button> <span>{counter.value}</span> <button onClick={() => counter.decrement()}>Decrement</button> </div> </div> ); }) ); export default App;

Attributs de qualité

  • Convivialité . Un magasin observable est le point d'entrée unique pour la gestion de l'état. Cela simplifie l'utilisation de MobX car vous avez le seul endroit pour modifier.
  • Maintenabilité . C'est un inconvénient considérable. Sans connaissance de l'API RxJS, vous ne pourrez pas obtenir le résultat souhaité. L'utilisation de MobX dans une équipe peu qualifiée peut entraîner des problèmes d'incohérence d'état.
  • Performances . MobX se compose de boutiques indépendantes et vous permet de vous abonner aux seules dont vous avez besoin. C'est très efficace.
  • Testabilité . Les magasins observables sont des objets JavaScript simples avec des fonctionnalités réactives cachées à l'intérieur. Le test est le même que pour toute autre classe JavaScript.
  • Évolutivité . Les magasins observables sont divisés logiquement ; il n'y a aucune difficulté à faire évoluer MobX.
  • Modifiable . MobX permet de créer des observables personnalisés avec des comportements modifiés. De plus, il existe un concept appelé réactions. Les réactions modélisent les effets secondaires automatiques. Ces éléments rendent MobX très personnalisable.
  • Réutilisabilité . MobX est indépendant des frameworks, il est donc très bon pour la réutilisation.
  • Écosystème . Il existe des centaines d'extensions disponibles pour MobX.
  • Communauté . MobX a beaucoup de fans dévoués. Il y a environ 1 600 questions (~ 1 000 réponses) avec la balise mobx sur Stack Overflow.
  • Pouls . MobX est mis à jour et entretenu régulièrement.

Recul

Recoil est un nouveau venu, la dernière idée originale de l'équipe React. L'idée de base derrière cela est une implémentation simple des fonctionnalités React manquantes comme l'état partagé et les données dérivées.

Vous vous demandez peut-être pourquoi une bibliothèque expérimentale est examinée pour les projets au niveau de l'entreprise. Tout d'abord, Recoil est l'un des sujets les plus discutés dans la communauté React en ce moment. Deuxièmement, Recoil est soutenu par Facebook et déjà utilisé dans certaines de ses applications, ce qui signifie qu'il deviendra une version stable à un moment donné. Enfin, c'est une approche entièrement nouvelle pour partager l'état dans React, et je suis sûr que même si Recoil est obsolète, il y aura un autre outil qui suivra le même chemin.

Recoil est construit sur deux termes : atom et selector . Un atome est une pièce à état partagé. Un composant peut s'abonner à un atome pour obtenir/définir sa valeur.

Diagramme illustrant la gestion des états avec Recoil, montrant comment les composants peuvent s'abonner à un atome pour récupérer ou définir sa valeur.

Comme vous pouvez le voir dans l'image, seuls les composants souscrits sont restitués lorsque la valeur est modifiée. Cela rend Recoil très performant.

Une autre grande chose que Recoil a prête à l'emploi est le sélecteur . Le sélecteur est une valeur agrégée à partir d'un atome ou d'un autre sélecteur. Pour les consommateurs, il n'y a pas de différence entre l'atome et le sélecteur, il leur suffit de s'abonner à une partie réactive et de l'utiliser.

Diagramme illustrant l'utilisation des sélecteurs dans Recoil, leur relation avec les atomes et les changements causés par différentes valeurs.

Chaque fois qu'un atome/sélecteur est modifié, les sélecteurs qui l'utilisent (c'est-à-dire qui y sont abonnés) sont réévalués.

Exemple d'API de recul

Le code de Recoil est bien plus différent que celui de ses concurrents. Il est basé sur les crochets React et se concentre davantage sur la structure de l'état que sur la mutation de cet état.

CodeSandbox

 // atoms/counter.js import { atom } from "recoil"; const counterAtom = atom({ key: "counter", default: 0 }); export default counterAtom; // index.js import React from "react"; import ReactDOM from "react-dom"; import { RecoilRoot } from "recoil"; import App from "./App"; ReactDOM.render( <RecoilRoot> <App /> </RecoilRoot>, document.getElementById("root") ); // App.js import React from "react"; import { useRecoilState } from "recoil"; import counterAtom from "./atoms/counter"; const App = () => { const [count, setCount] = useRecoilState(counterAtom); return ( <div> <div> <button onClick={() => setCount(count + 1)}>Increment</button> <span>{count}</span> <button onClick={() => setCount(count - 1)}>Decrement</button> </div> </div> ); }; export default App;

Attributs de qualité

  • Convivialité . Recoil est l'un des outils les plus faciles à utiliser car il fonctionne comme useState dans React.
  • Maintenabilité . Tout ce que vous avez à faire dans Recoil est de maintenir des sélecteurs et des crochets à l'intérieur des composants - plus de valeur, moins de passe-partout.
  • Performances . Recoil construit un arbre d'état en dehors de React. L'arbre d'état vous permet d'obtenir et d'écouter les éléments dont vous avez besoin, et non les changements de l'arbre entier. Il est également bien optimisé sous le capot.
  • Testabilité . Recoil fournit un mécanisme pour tester ses atomes et ses sélecteurs.
  • Évolutivité . Un état qui se divise en plusieurs parties indépendantes en fait un bon acteur de l'évolutivité.
  • Modifiable . Recoil est uniquement responsable du stockage des valeurs et de leurs agrégations. Il n'a pas de flux de données, il peut donc être personnalisé facilement.
  • Réutilisabilité . Recoil repose sur React. Il ne peut pas être réutilisé ailleurs.
  • Écosystème . Il n'y a pas d'écosystème pour Recoil pour le moment.
  • Communauté . Recoil est trop récent pour avoir une grande communauté. Il y a environ 70 questions avec la balise recoiljs sur Stack Overflow.
  • Pouls . Recoil est rarement mis à jour (six mois se sont écoulés entre ses deux mises à jour les plus récentes). Il a également de nombreux problèmes ouverts sur GitHub.

Choisir le bon outil de gestion de l'état de réaction

Comment ces bibliothèques de gestion d'état globales React s'empilent-elles lorsqu'il s'agit d'applications d'entreprise ?

Recoil est jeune et frais, mais n'a pas de communauté ni d'écosystème pour le moment. Même si Facebook y travaille et que l'API semble prometteuse, une énorme application React ne peut pas s'appuyer sur une bibliothèque avec un faible support communautaire. De plus, c'est expérimental, ce qui le rend encore plus dangereux. Ce n'est certainement pas une bonne option pour les applications d'entreprise React aujourd'hui, mais cela vaut la peine de garder un œil dessus.

MobX et Redux ne partagent aucun de ces problèmes et la plupart des grands acteurs du marché les utilisent. Ce qui les rend différents les uns des autres, c'est la courbe d'apprentissage. MobX nécessite une compréhension de base de la programmation réactive. Si les ingénieurs impliqués dans le projet ne sont pas suffisamment qualifiés, l'application peut se retrouver avec des incohérences de code, des problèmes de performances et un temps de développement accru. MobX est acceptable et répondra à vos besoins si votre équipe est soucieuse de réactivité.

Redux a également quelques problèmes, principalement en ce qui concerne l'évolutivité et les performances. Cependant, contrairement à MobX, il existe des solutions éprouvées à ces problèmes.

En tenant compte de tous les avantages et inconvénients, et compte tenu de mon expérience personnelle, je recommande Redux comme la meilleure option pour les applications d'entreprise React.