135 votes

Angular 6 - Pourquoi utiliser @ngrx/store plutôt que l'injection de service

Je suis en train d'apprendre Angular 6 avec @ngrx/store récemment alors qu'un des tutoriels consiste à utiliser @ngrx/store pour la gestion de l'état, mais je ne comprends pas les avantages d'utiliser @ngrx/store en coulisses.

Par exemple, pour une action simple de connexion et d'inscription, précédemment en utilisant le service (appelons-le AuthService) nous pourrions l'utiliser pour appeler l'API backend, stocker "userInfo" ou "token" dans AuthService, rediriger l'utilisateur vers la page d'accueil "HOME" et nous pouvons injecter AuthService dans n'importe quel composant où nous avons besoin d'obtenir les informations de l'utilisateur en utilisant DI, ce qui signifie simplement qu'un seul fichier AuthService gère tout.

Maintenant, si nous utilisons @ngrx/store, nous devons définir l'Action/State/Reducer/Effects/Selector qui nécessite probablement d'écrire dans 4 ou 5 fichiers pour gérer l'action ou l'événement ci-dessus, puis parfois nous devons encore appeler l'API backend en utilisant le service, ce qui semble beaucoup plus compliqué et redondant...

Dans un autre scénario, j'ai même vu certaines pages utiliser @ngrx/store pour stocker l'objet ou la liste d'objets comme des données de grille., est-ce pour une sorte d'utilisation de stockage en mémoire?

Donc, revenons à la question, pourquoi utilisons-nous @ngrx/store plutôt que l'enregistrement de service ici dans le projet Angular? Je sais que c'est pour une utilisation de " GESTION D'ÉTAT", mais qu'est-ce exactement que la "GESTION D'ÉTAT"? Est-ce quelque chose comme un journal des transactions et quand avons-nous besoin de cela? Pourquoi le gérerions-nous côté frontend? N'hésitez pas à partager vos suggestions ou votre expérience dans le domaine de @ngrx/store!

23 votes

L'année dernière, j'ai commencé un nouvel emploi dans une entreprise. Ils utilisaient Angular avec Redux. Je n'ai pas encore touché à Redux, mais je développe en Angular depuis sa sortie en version bêta. Ma première impression a été "mais c'est quoi ce truc?" Tellement de complications juste pour communiquer avec une API et s'abonner à ces données. Ils utilisaient littéralement Redux pour tout! C'était tellement le bazar que c'était impossible de travailler. Il n'y a vraiment aucun besoin d'intégrer Redux / Ngrx à une application Angular. Vous pouvez tout faire "à la manière d'Angular".

12 votes

NgRx augmente exponentiellement la complexité du code avec beaucoup de code redondant inutile. D'autre part, il n'offre guère plus que ce qu'Angular, en tant que framework complet, a déjà offert par défaut. Ce billet de blog couvre toutes les informations dont vous avez besoin : Gestion de l'état de l'application Angular : Vous n'avez pas besoin de magasins de données externes

3 votes

Désolé les gars je ne suis pas d'accord. Quand votre projet atteint une certaine taille, vous commencez à rencontrer des problèmes pour maintenir tout à jour. J'utilisais beaucoup de BehavoirSubjects et l'augmentation de la complexité signifiait que je réinventais NGRX mais maladroitement. J'ai réécrit mon application en utilisant NGRX et j'ai accès au store partout. Les changements de syntaxe de V8 ont réduit la quantité de code redondant également. Mon projet est plus propre, plus facile à lire et plus rapide à exécuter.

47voto

Je pense que vous devriez lire ces deux articles sur Ngrx Store :

Si le premier explique les principaux problèmes résolus par Ngrx Store, il cite également cette déclaration du guide React "qui semble s'appliquer également à Flux, Redux, Ngrx Store ou toute solution de store en général" :

Vous saurez si vous avez besoin de Flux. Si vous n'êtes pas sûr d'en avoir besoin, c'est que vous n'en avez pas besoin.

Pour moi, Ngrx Store résout plusieurs problèmes. Par exemple, lorsque vous devez gérer des observables et lorsque la responsabilité de certaines données observables est partagée entre différents composants. Dans ce cas, les actions du store et le reducer garantissent que les modifications des données seront toujours effectuées "de la bonne manière".

Il fournit également une solution fiable pour le caching des requêtes http. Vous pourrez stocker les requêtes et leurs réponses, afin de vérifier que la requête que vous êtes en train de faire n'a pas encore de réponse stockée.

Le deuxième article concerne ce qui a fait apparaître de telles solutions dans le monde React avec le problème du compteur de messages non lus de Facebook.

Concernant votre solution de stocker des données non observables dans des services. Cela fonctionne bien lorsque vous travaillez avec des données constantes. Mais lorsque plusieurs composants doivent mettre à jour ces données, vous rencontrerez probablement des problèmes de détection de changement et de mise à jour incorrecte, que vous pourriez résoudre avec :

  • le pattern observer avec un Subject privé, un Observable public et une fonction next
  • Ngrx Store

25voto

Sammi Points 1

Je lis presque uniquement les avantages de Ngrx et d'autres bibliothèques de stockage Redux similaires, tandis que les compromis (à mon avis) coûteux semblent être balayés avec beaucoup trop de facilité. C'est souvent la seule raison que je vois donnée : "La seule raison de ne pas utiliser Ngrx est si votre application est petite et simple". Cela (je dirais) est tout simplement un raisonnement incomplet et pas assez bon.

Voici mes plaintes concernant Ngrx :

  • Vous avez la logique répartie dans plusieurs fichiers différents, ce qui rend le code difficile à lire et à comprendre. Cela va à l'encontre des principes de cohésion de base du code et de la localité. Devoir sauter d'un endroit à un autre pour lire comment une opération est effectuée est mentalement éprouvant et peut entraîner une surcharge cognitive et une épuisement.
  • Avec Ngrx, vous devez écrire beaucoup plus de code, ce qui augmente les chances de bugs. Plus de code -> plus d'endroits où les bugs peuvent apparaître.
  • Un magasin Ngrx peut devenir un dépotoir de toutes sortes de choses, sans queue ni tête. Cela peut devenir un fourre-tout global de choses que personne ne peut avoir une vue d'ensemble cohérente. Il peut grandir et grandir jusqu'à ce que personne ne le comprenne plus.
  • J'ai vu beaucoup de clonage inutile d'objets profonds dans les applications Ngrx, ce qui a causé de réels problèmes de performance. Une application particulière sur laquelle j'ai été affectée prenait 40 ms pour persister des données dans le magasin en raison du clonage profond d'un énorme objet de magasin. Cela représente plus de deux images manquées si vous essayez d'atteindre un framerate fluide de 60 ips. Chaque interaction semblait saccadée à cause de cela.
  • La plupart des choses que fait Ngrx peuvent être faites beaucoup plus simplement en utilisant un modèle de service/facade de base qui expose des observables à partir de sujets rxjs.

Mettez simplement des méthodes sur des services/facades qui retournent des observables - une telle méthode remplace le réducteur, le magasin et le sélecteur de Ngrx. Et ensuite, mettez d'autres méthodes sur le service/facade pour déclencher le fait que des données soient poussées sur ces observables - ces méthodes remplacent vos actions et effets de Ngrx. Ainsi, au lieu de réducteurs+magasins+sélecteurs, vous avez des méthodes qui retournent des observables. Au lieu d'actions+effets, vous avez des méthodes qui produisent des données pour les observables. D'où viennent les données vous appartient, vous pouvez récupérer quelque chose ou calculer quelque chose, et ensuite appeler simplement subject.next() avec les données que vous voulez pousser.

  • Les connaissances rxjs dont vous avez besoin pour utiliser ngrx vous rendront déjà compétent dans l'utilisation de rxjs nu de toute façon.
  • Si vous avez plusieurs composants qui dépendent de certaines données communes, alors vous n'avez toujours pas besoin de ngrx, car le modèle de service/facade de base gère déjà cela explicitement.
  • Si plusieurs services dépendent de données communes entre eux, alors vous créez simplement un service commun entre ces services. Vous n'avez toujours pas besoin de ngrx. Ce sont des services tout le long, tout comme ce sont des composants tout le long.

Pour moi, Ngrx ne semble pas si bon à l'analyse finale.

C'est essentiellement un sujet Rxjs Enterprise™ gonflé et sur-ingénierie, quand vous auriez pu simplement utiliser le bon vieux et fiable sujet Rxjs. Écoutez-moi les enfants, la vie est trop courte pour une complexité inutile. En restant aux stricts nécessités. Les simples nécessités. Oubliez vos soucis et vos problèmes.

2 votes

Je suis d'accord avec cela. La raison pour laquelle j'utilise NgRx est très similaire à celle de l'utilisation de RxJs. La réponse est toujours "parce que vous pouvez diffuser des valeurs avec des Observables". Vraiment? Ce n'est pas une bonne raison pour abandonner complètement les Promesses - surtout compte tenu du support linguistique intégré async/await qui rend votre code tellement plus facile à lire et à comprendre que tous les rappels complexes que vous devez utiliser dans RxJs.

1 votes

Eh bien, si vous avez besoin de diffuser des données, alors une promesse ne fonctionnera pas, car elle ne peut être émise qu'une fois. Dans ce cas, vous avez besoin d'une bibliothèque observable comme rxjs, car vous ne voulez pas non plus rester bloqué dans l'enfer des rappels, c'est certain.

1 votes

Je n'ai jamais construit d'application ayant besoin de diffuser des données. Toutes mes applications professionnelles ont besoin d'appeler une api et d'obtenir une seule réponse en retour. Et utiliser RxJs juste parce que la 1 application que je pourrais construire dans 10 ans pourrait avoir besoin de diffusion, est ridicule.

10voto

dallows Points 137

J'ai travaillé avec NgRx depuis plus de trois ans maintenant. Je l'ai utilisé sur de petits projets, où c'était pratique mais pas nécessaire, et je l'ai utilisé dans des applications où c'était parfaitement adapté. Pendant ce temps, j'ai eu l'occasion de travailler sur un projet qui ne l'utilisait pas et je dois dire qu'il en aurait bénéficié.

Sur le projet actuel, j'étais chargé de concevoir l'architecture de la nouvelle application FE. On m'a confié la tâche de refondre complètement l'application existante qui, pour les mêmes besoins, utilisait une approche non NgRx et qui était boguée, difficile à comprendre et à maintenir et sans documentation. J'ai décidé d'utiliser NgRx là et je l'ai fait pour les raisons suivantes :

  • L'application a plus d'un acteur sur les données. Le serveur utilise le SSE pour pousser des mises à jour d'état qui sont indépendantes des actions de l'utilisateur.
  • Au démarrage de l'application, nous chargeons la plupart des données disponibles qui sont ensuite partiellement mises à jour avec SSE.
  • Divers éléments de l'interface utilisateur sont activés/désactivés en fonction de plusieurs conditions provenant du serveur et des décisions de l'utilisateur.
  • L'interface utilisateur a plusieurs variations. Les événements du serveur peuvent changer les éléments de l'interface utilisateur actuellement visibles (textes dans les dialogues) et même les actions de l'utilisateur peuvent modifier l'apparence et le fonctionnement de l'interface utilisateur (le dialogue récurrent peut être remplacé par une notification si l'utilisateur cliqué sur un bouton).
  • L'état de plusieurs éléments de l'interface utilisateur doit être préservé afin que lorsque l'utilisateur quitte la page et y revienne, le même contenu (ou mis à jour via SSE) soit visible.

Comme vous pouvez le voir, les exigences ne correspondent pas à la page web standard des opérations CRUD. Le faire à la manière "Angular" a apporté une telle complexité au code qu'il est devenu extrêmement difficile à maintenir et, ce qui est pire, lorsque j'ai rejoint l'équipe, les deux derniers membres d'origine partaient sans aucune documentation sur cette solution personnalisée, non NgRx.

Maintenant, après un an depuis la refonte de l'application pour utiliser NgRx, je pense que je peux résumer les avantages et les inconvénients.

Les avantages :

  • L'application est mieux organisée. La représentation de l'état est facile à lire, regroupée par but ou origine des données et simple à étendre.
  • Nous nous sommes débarrassés de nombreuses usines, façades et classes abstraites qui avaient perdu leur utilité. Le code est plus léger, et les composants sont 'plus simples', avec moins de manipulations cachées venant d'ailleurs.
  • Les calculs d'état compliqués sont simplifiés en utilisant des effets et des sélecteurs et la plupart des composants peuvent désormais être entièrement fonctionnels en injectant simplement le store et en envoyant les actions ou en sélectionnant la tranche nécessaire de l'état tout en gérant plusieurs actions en même temps.
  • En raison des modifications apportées aux exigences de l'application, nous avons été contraints de refondre le store déjà et c'était principalement du copier-coller et un peu de renommage.
  • Grâce aux outils de développement Redux, il est plus facile de déboguer et d'optimiser (oui vraiment)
  • C'est le plus important - même si notre état lui-même est unique, la gestion du store que nous utilisons ne l'est pas. Il a un support, il a une documentation et ce n'est pas impossible de trouver des solutions à certains problèmes difficiles sur internet.
  • Petit avantage, NgRx est une autre technologie que vous pouvez ajouter à votre CV :)

Les inconvénients :

  • Mes collègues étaient nouveaux dans NgRx et il leur a fallu un certain temps pour s'adapter et le comprendre pleinement.
  • À certaines occasions, nous avons introduit le problème où certaines actions étaient déclenchées plusieurs fois et il était difficile d'en trouver la cause et de le résoudre
  • Nos Effets sont énormes, c'est vrai. Ils peuvent devenir compliqués mais c'est pourquoi nous avons des demandes de tirage. Et si ce code n'était pas là, il finirait quand même quelque part ailleurs :)
  • Le plus gros problème ? Les actions sont différenciées par leur type de chaîne. Copiez une action, oubliez de la renommer et boom, quelque chose de différent se produit de ce à quoi vous vous attendiez, et vous n'avez aucune idée de pourquoi.

En conclusion, je dirais que dans notre cas, NgRx était un excellent choix. C'est exigeant au début mais plus tard tout semble naturel et logique. De plus, lorsque vous vérifiez les exigences, vous remarquerez que c'est un cas spécial. Je comprends les critiques contre NgRx et dans certains cas, je les soutiendrais mais pas sur ce projet. Aurions-nous pu le faire en utilisant la manière 'Angular' ? Bien sûr, cela a été fait de cette manière auparavant, mais c'était un gâchis. C'était toujours plein de code de base, de choses se produisant à différents endroits sans raisons évidentes et plus encore.

Toute personne ayant la chance de comparer ces deux versions dirait que la version NgRx est meilleure.

0 votes

Simplement la meilleure réponse! Entièrement d'accord sur tout ce qui a été mentionné. J'ai 3 ans d'expérience avec NgRx - j'ai déjà rencontré tous les avantages et inconvénients mentionnés.

9voto

Aleksa Points 1272

Il y a aussi une 3ème option, avoir des données dans le service et utiliser directement le service dans le html, par exemple *ngFor="let item of userService.users". Donc lorsque vous mettez à jour userService.users dans le service après une action d'ajout ou de mise à jour, elle est automatiquement rendue dans le html, pas besoin d'observables, d'événements ou de store.

17 votes

Cela ne fonctionne pas en AOT si le service est injecté en tant que service privé. La meilleure pratique est de ne pas exposer un service au modèle d'un composant. Au lieu de cela, gardez une variable dans le composant et obtenez/définissez-la en fonction de la variable du service.

0 votes

Nous devons injecter le service en public pour l'exposer au modèle de composant.

3voto

Derek Kite Points 885

Si les données de votre application sont utilisées dans plusieurs composants, alors un certain type de service est nécessaire pour partager les données. Il existe de nombreuses façons de le faire.

Une application modérément complexe finira par ressembler à une structure front-end back-end, avec la manipulation des données effectuée dans des services, exposant les données via des observables aux composants.

À un moment donné, vous devrez écrire un type d'API pour vos services de données, comment obtenir des données et les transmettre, des requêtes, etc. Beaucoup de règles comme l'immuabilité des données, et des chemins uniques bien définis pour modifier les données. Pas très différents du backend du serveur, mais beaucoup plus rapide et réactif que les appels d'API.

Votre API finira par ressembler à l'une des nombreuses bibliothèques de gestion d'état déjà existantes. Elles existent pour résoudre des problèmes difficiles. Vous n'en aurez peut-être pas besoin si votre application est simple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X