Dans une application Flux, il ne devrait y avoir qu'un seul Dispatcher. Toutes les données transitent par ce hub central. Avoir un répartiteur singleton lui permet de gérer tous les magasins. Cela devient important lorsque vous avez besoin de la mise à jour du magasin n ° 1 proprement dit, puis que le magasin n ° 2 se met à jour lui-même en fonction de l'action et de l'état du magasin n ° 1. Flux suppose que cette situation est une éventualité dans une grande application. Idéalement, cette situation n'aurait pas besoin de se produire et les développeurs devraient s'efforcer d'éviter cette complexité, si possible. Mais le répartiteur singleton est prêt à le gérer le moment venu.
Les magasins sont également des singletons. Ils doivent rester aussi indépendants et découplés que possible - un univers autonome que l'on peut interroger à partir d'une Controller-View. La seule route vers le magasin passe par le rappel qu'il enregistre auprès du répartiteur. La seule issue est les fonctions getter. Les magasins publient également un événement lorsque leur état a changé, de sorte que Controller-Views puisse savoir quand demander le nouvel état, à l'aide des getters.
Dans votre exemple d'application, il y en aurait un seul PostStore
. Ce même magasin pourrait gérer les messages sur une "page" (pseudo-page) qui ressemble plus au fil d'actualité de FB, où les messages apparaissent de différents utilisateurs. Son domaine logique est la liste des messages et il peut gérer n'importe quelle liste de messages. Lorsque nous passons d'une pseudo-page à une pseudo-page, nous souhaitons réinitialiser l'état du magasin pour refléter le nouvel état. Nous pourrions également vouloir mettre en cache l'état précédent dans localStorage pour optimiser les allers-retours entre les pseudo-pages, mais mon inclination serait de configurer un PageStore
qui attend tous les autres magasins, gère la relation avec localStorage pour tous les magasins sur la pseudo-page, puis met à jour son propre état. Notez que ceciPageStore
ne stockera rien sur les messages - c'est le domaine duPostStore
. Il saurait simplement si une pseudo-page particulière a été mise en cache ou non, car les pseudo-pages sont son domaine.
Le PostStore
aurait une initialize()
méthode. Cette méthode effacerait toujours l'ancien état, même s'il s'agit de la première initialisation, puis créerait l'état en fonction des données reçues via l'action, via le Dispatcher. Passer d'une pseudo-page à une autre impliquerait probablement une PAGE_UPDATE
action, qui déclencherait l'invocation de initialize()
. Il y a des détails à résoudre autour de la récupération des données du cache local, de la récupération des données du serveur, du rendu optimiste et des états d'erreur XHR, mais c'est l'idée générale.
Si une pseudo-page particulière n'a pas besoin de tous les Stores de l'application, je ne suis pas tout à fait sûr qu'il y ait une raison de détruire les non utilisées, autre que des contraintes de mémoire. Mais les magasins ne consomment généralement pas beaucoup de mémoire. Vous devez simplement vous assurer de supprimer les écouteurs d'événements dans les vues de contrôleur que vous êtes en train de détruire. Ceci est fait dans la componentWillUnmount()
méthode de React .
UserListStore
, avec tous les utilisateurs pertinents. Et chaque utilisateur aurait quelques indicateurs booléens décrivant la relation avec le profil utilisateur actuel. Quelque chose comme{ follower: true, followed: false }
, par exemple. Les méthodesgetFolloweds()
etgetFollowers()
récupéreraient les différents ensembles d'utilisateurs dont vous avez besoin pour l'interface utilisateur.(Remarque: j'ai utilisé la syntaxe ES6 en utilisant l'option JSX Harmony.)
En guise d'exercice, j'ai écrit un exemple d'application Flux qui permet de parcourir
Github users
et de déposer.Il est basé sur la réponse de fisherwebdev mais reflète également une approche que j'utilise pour normaliser les réponses API.
Je l'ai fait pour documenter quelques approches que j'ai essayées en apprenant Flux.
J'ai essayé de le garder proche du monde réel (pagination, pas de fausses API localesStorage).
Il y a quelques éléments qui m'intéressaient particulièrement:
switch
avec des actions ;Comment je classe les magasins
J'ai essayé d'éviter une partie de la duplication que j'ai vue dans d'autres exemples de Flux, en particulier dans les magasins. J'ai trouvé utile de diviser logiquement les magasins en trois catégories:
Les magasins de contenu contiennent toutes les entités d'application. Tout ce qui a un identifiant a besoin de son propre Content Store. Les composants qui rendent des éléments individuels demandent aux Content Stores les nouvelles données.
Les magasins de contenu récupèrent leurs objets de toutes les actions du serveur. Par exemple,
UserStore
regardeaction.response.entities.users
s'il existe quelle que soit l'action déclenchée. Il n'y a pas besoin d'unswitch
. Normalizr facilite l'aplatissement des réponses d'API à ce format.Les magasins de listes gardent une trace des identifiants des entités qui apparaissent dans une liste globale (par exemple «flux», «vos notifications»). Dans ce projet, je n'ai pas de tels magasins, mais je pensais les mentionner quand même. Ils gèrent la pagination.
Ils répondent normalement à quelques actions (par exemple
REQUEST_FEED
,REQUEST_FEED_SUCCESS
,REQUEST_FEED_ERROR
).Les magasins de listes indexées sont comme les magasins de listes, mais ils définissent une relation un-à-plusieurs. Par exemple, «abonnés de l'utilisateur», «astronomes du référentiel», «référentiels de l'utilisateur». Ils gèrent également la pagination.
Ils répondent aussi normalement que quelques actions (par exemple
REQUEST_USER_REPOS
,REQUEST_USER_REPOS_SUCCESS
,REQUEST_USER_REPOS_ERROR
).Dans la plupart des applications sociales, vous en aurez beaucoup et vous voulez pouvoir en créer rapidement une de plus.
Remarque: ce ne sont pas des classes réelles ou quelque chose du genre; c'est comme ça que j'aime penser aux magasins. J'ai cependant fait quelques aides.
StoreUtils
createStore
Cette méthode vous donne le magasin le plus basique:
Je l'utilise pour créer tous les magasins.
isInBag
,mergeIntoBag
Petits assistants utiles pour les magasins de contenu.
PaginatedList
Stocke l'état de pagination et applique certaines assertions (impossible de récupérer la page lors de la récupération, etc.).
PaginatedStoreUtils
createListStore
,createIndexedListStore
,createListActionHandler
Rend la création de magasins de listes indexées aussi simple que possible en fournissant des méthodes standard et la gestion des actions:
createStoreMixin
Un mixin qui permet aux composants de se connecter aux magasins qui les intéressent, par exemple
mixins: [createStoreMixin(UserStore)]
.la source
Ainsi, dans Reflux, le concept de Dispatcher est supprimé et vous n'avez qu'à penser en termes de flux de données à travers les actions et les magasins. C'est à dire
Chaque flèche ici modélise la façon dont le flux de données est écouté, ce qui signifie à son tour que les données circulent dans la direction opposée. Le chiffre réel du flux de données est le suivant:
Dans votre cas d'utilisation, si j'ai bien compris, nous avons besoin d'une
openUserProfile
action qui initie le chargement et le changement de page du profil utilisateur, ainsi que des actions de chargement de publications qui chargeront les publications lorsque la page de profil utilisateur est ouverte et pendant l'événement de défilement infini. J'imagine donc que nous avons les magasins de données suivants dans l'application:Dans Reflux, vous le configurez comme ceci:
Les actions
Le magasin de pages
Le magasin de profils utilisateur
Le magasin d'articles
Les composants
Je suppose que vous avez un composant pour la vue de la page entière, la page de profil utilisateur et la liste des publications. Les éléments suivants doivent être câblés:
Action.openUserProfile
avec l'ID correct pendant son événement de clic.currentPageStore
afin de savoir à quelle page basculer.currentUserProfileStore
afin de savoir quelles données de profil utilisateur affichercurrentPostsStore
pour recevoir les messages chargésAction.loadMorePosts
.Et cela devrait être à peu près tout.
la source