Si les magasins conservent leur propre état et ont la possibilité d'appeler des services de réseau et de stockage de données pour ce faire ... auquel cas les actions ne sont que des passeurs de messages stupides,
-OU-
... les magasins devraient-ils être des destinataires stupides de données immuables provenant des actions (et les actions être celles qui récupèrent / envoient des données entre des sources externes? Dans ce cas, le magasin agirait comme des modèles de vue et serait capable d'agréger / filtrer leurs données avant de définir leur propre état de base sur les données immuables qui leur ont été alimentées par l'action.
Il me semble que ce devrait être l’un ou l’autre (plutôt qu’un mélange des deux). Dans l'affirmative, pourquoi l'un est-il préféré / recommandé par rapport à l'autre?
la source
Réponses:
J'ai vu le modèle de flux implémenté dans les deux sens, et après avoir fait les deux moi-même (initialement avec l'ancienne approche), je pense que les magasins devraient être des destinataires stupides des données des actions, et que le traitement asynchrone des écritures devrait vivre dans le créateurs d'action. (Les lectures asynchrones peuvent être gérées différemment .) D'après mon expérience, cela présente quelques avantages, par ordre d'importance:
Vos magasins deviennent complètement synchrones. Cela rend la logique de votre magasin beaucoup plus facile à suivre et très facile à tester: instanciez simplement un magasin avec un état donné, envoyez-lui une action et vérifiez si l'état a changé comme prévu. En outre, l'un des concepts de base du flux est d'empêcher les envois en cascade et d'empêcher plusieurs envois à la fois; c'est très difficile à faire lorsque vos magasins effectuent un traitement asynchrone.
Toutes les expéditions d'actions proviennent des créateurs d'action. Si vous gérez des opérations asynchrones dans vos magasins et que vous souhaitez garder les gestionnaires d'actions de vos magasins synchrones (et vous devriez le faire pour obtenir les garanties d'envoi unique de flux), vos magasins devront déclencher des actions SUCCESS et FAIL supplémentaires en réponse à des actions asynchrones. En traitement. Placer ces dépêches dans les créateurs d'action aide à la place à séparer les tâches des créateurs d'action et des magasins; De plus, vous n'avez pas à fouiller dans la logique de votre magasin pour déterminer d'où les actions sont expédiées. Une action asynchrone typique dans ce cas peut ressembler à quelque chose comme ceci (changez la syntaxe des
dispatch
appels en fonction de la saveur du flux que vous utilisez):La logique qui pourrait autrement être dupliquée à travers diverses actions doit être extraite dans un module séparé; dans cet exemple, ce module serait
SomeDataAccessLayer
, qui gère la requête Ajax réelle.Vous avez besoin de moins de créateurs d'action. C'est moins grave, mais agréable à avoir. Comme mentionné dans # 2, si vos magasins ont une gestion de répartition des actions synchrones (et ils devraient), vous devrez déclencher des actions supplémentaires pour gérer les résultats des opérations asynchrones. Faire les distributions dans les créateurs d'action signifie qu'un seul créateur d'action peut distribuer les trois types d'action en gérant le résultat de l'accès asynchrone aux données lui-même.
la source
"SOME_ACTION"
), utiliser une API pour faire une requête (SomeDataAccessLayer.doSomething(userId)
) qui renvoie une promesse, et dans les deux.then
fonctions, envoyer des actions supplémentaires. L'état de la demande peut (plus ou moins) mapper sur l'état de stockage si l'application a besoin de connaître l'état de l'état. Comment ces cartes dépendent de l'application (par exemple, peut-être que chaque commentaire a un état d'erreur individuel, à la Facebook, ou peut-être qu'il y a un composant d'erreur global)J'ai tweeté cette question aux développeurs de Facebook et la réponse de Bill Fisher a été:
la source
a call from store works better when action triggers from non-human driver
?Les magasins doivent tout faire, y compris récupérer les données et signaler aux composants que les données du magasin ont été mises à jour. Pourquoi? Parce que les actions peuvent alors être légères, jetables et remplaçables sans influencer les comportements importants. Tous les comportements et fonctionnalités importants se produisent dans le magasin. Cela évite également la duplication de comportements qui seraient autrement copiés dans deux actions très similaires mais différentes. Les magasins sont votre source unique de (gestion de) la vérité.
Dans chaque implémentation de Flux que j'ai vue, les Actions sont essentiellement des chaînes d'événements transformées en objets, comme traditionnellement vous auriez un événement nommé "anchor: clicked" mais dans Flux, il serait défini comme AnchorActions.Clicked. Ils sont même si "stupides" que la plupart des implémentations ont des objets Dispatcher séparés pour envoyer réellement les événements aux magasins qui écoutent.
Personnellement, j'aime l'implémentation de Flux par Reflux où il n'y a pas d'objets Dispatcher séparés et les objets Action effectuent le dispatching eux-mêmes.
edit: Flux de Facebook récupère en fait des "créateurs d'action" afin qu'ils utilisent des actions intelligentes. Ils préparent également la charge utile à l'aide des magasins:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/actions/ChatMessageActionCreators.js#L27 (lignes 27 et 28)
Le rappel à la fin déclencherait alors une nouvelle action cette fois avec les données extraites comme charge utile:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/utils/ChatWebAPIUtils.js#L51
Alors je suppose que c'est la meilleure solution.
la source
Je vais fournir un argument en faveur des actions «stupides».
En plaçant la responsabilité de la collecte des données de vue dans vos actions, vous associez vos actions aux exigences de données de vos vues.
En revanche, les actions génériques, qui décrivent de manière déclarative l' intention de l'utilisateur, ou une transition d'état dans votre application, permettent à tout magasin qui répond à cette action de transformer l'intention, en un état spécialement conçu pour les vues qui y sont abonnées.
Cela se prête à des magasins plus nombreux, mais plus petits et plus spécialisés. Je défends ce style parce que
Le but d'un magasin est de fournir des données aux vues. Le nom «Action» me suggère que son but est de décrire un changement dans ma candidature.
Supposons que vous deviez ajouter un widget à une vue de tableau de bord existante, qui montre de nouvelles données agrégées sophistiquées que votre équipe backend vient de déployer.
Avec les actions «intelligentes», vous devrez peut-être modifier votre action «rafraîchir le tableau de bord» pour utiliser la nouvelle API. Cependant, «Actualiser le tableau de bord» dans un sens abstrait n'a pas changé. Les exigences de données de vos vues sont ce qui a changé.
Avec des actions "stupides", vous pouvez ajouter un nouveau magasin pour le nouveau widget à consommer, et le configurer de sorte que lorsqu'il reçoit le type d'action "refresh-dashboard", il envoie une demande pour les nouvelles données et les expose à le nouveau widget une fois qu'il est prêt. Il est logique pour moi que lorsque la couche de vue a besoin de plus de données ou de données différentes, les choses que je change sont les sources de ces données: les magasins.
la source
La démo flux- react -router-demo de gaeron a une belle variante utilitaire de l'approche «correcte».
Un ActionCreator génère une promesse à partir d'un service d'API externe, puis transmet la promesse et trois constantes d'action à une
dispatchAsync
fonction dans un proxy / Dispatcher étendu.dispatchAsync
enverra toujours la première action, par exemple «GET_EXTERNAL_DATA» et une fois la promesse renvoyée, elle enverra soit «GET_EXTERNAL_DATA_SUCCESS» ou «GET_EXTERNAL_DATA_ERROR».la source
Si vous voulez un jour avoir un environnement de développement comparable à ce que vous voyez dans la célèbre vidéo Inventing on Principle de Bret Victor , vous devriez plutôt utiliser des magasins stupides qui ne sont qu'une projection d'actions / d'événements à l'intérieur d'une structure de données, sans aucun effet secondaire. Cela aiderait également si vos magasins étaient réellement membres de la même structure de données immuables globale, comme dans Redux .
Plus d'explications ici: https://stackoverflow.com/a/31388262/82609
la source