Un magasin d'actions pour des mises à jour optimistes est une bonne approche dans Redux / Flux?

J'ai travaillé avec des mises à jour optimistes dans une application React + Flux et j'ai vu deux choses:

  1. Que se passe-t-il si un utilisateur tente de fermer la fenêtre lorsqu'il existe des actions inachevées. Par exemple, dans Facebook, un message apparaît dans le mur, même s'il n'a pas vraiment persisté (c'est ce que font les mises à jour optimistes, une application plus adaptée à l'utilisateur). Mais, si un utilisateur affiche dans le mur et ferme immédiatement l'application (après la fermeture de session ou la fermeture de la fenêtre), le message pourrait échouer et il ne serait pas alerté.
  2. Je n'aime pas l'idée que les magasins gèrent leurs propres entités (par exemple, les messages) et la situation de l'action déclenchée pour persiste un message (chargement, réussite, échec?). Il mélange les choses.

Je travaille donc sur ceci et crée un ActionStore pour gérer l'état des actions déclenchées par les composants. Voici le code source et voici une démo en direct.

Cela fonctionne plus ou moins comme ceci:

  1. La racine de la hiérarchie des composants (container in redux) récupère le prochainId d'une nouvelle action et la transmet à ses enfants comme des accessoires (c'est laid).
  2. Un composant enfant déclenche une action: il conserve l'action pour le demander au magasin après et appelez le créateur d'actions.
  3. Le créateur d'action crée une nouvelle Action et renvoie une fonction au middleware.
  4. La fonction renvoyée à partir de l'Action crée une nouvelle promesse avec l'appel API et expédie une action du type XX_START.
  5. ActionStore écoute l'action XX_START et l'enregistre.
  6. Le composant enfant reçoit le nouvel état et trouve l'action avec l'identifiant sauvegardé et lui demande la situation actuelle: chargement, réussite ou échec.

Je l'ai fait principalement pour séparer l'état des «entités» de l'état des actions, mais permet également des actions de redéclenchement avec la même charge utile (cela pourrait être utile lorsque nous recevons un état de réponse 500 si le serveur est temporairement en panne ou si Le signal détaché de l'utilisateur).

En outre, avoir un stock d'actions permet de demander facilement s'ils sont en attente d'actions avant que l'utilisateur ne se déconnecte ou ne ferme la fenêtre.

Remarque: Je travaille avec une application Web de la page d'application unique contre une API de repos, je ne pense pas l'utiliser sur le rendu côté serveur

C'est une option viable de créer un ActionStore ou je brise des fondations de Redux / Flux? Cela pourrait mettre fin à la possibilité d'utiliser Réagir de recharge à chaud et de temps de déplacement?

Vous devriez répondre sans pitié, j'ai probablement fait un tas de choses moche, mais j'apprends React / Redux.

Pour les futurs lecteurs qui pourraient être un peu déconcertés: nous n'appelons plus ces fonctions "magasins": nous les appelons réducteurs . La question porte donc sur des actions de rappel réducteur .

Personnellement, je n'aime pas l'approche que vous proposez là-bas. Vous mettez la logique dans les actions et utilisez l'héritage pour cela. Au contraire, Redux prescrit des actions pour être des objets simples sans logique. Ils ne devraient pas «savoir» comment mettre à jour certains états, et ils ne devraient pas le retenir – au lieu de cela, ils devraient décrire ce qui s'est passé.

Je pense que l'approche pour la mise en œuvre de mises à jour optimistes dans Redux est similaire à la façon dont vous implémentiez Annuler dans Redux , qui à son tour s'inspire de l' architecture Elm . L'idée est que vous devriez écrire une fonction qui prend un réducteur (et quelques options) et renvoie un réducteur:

function optimistic(reducer) { return function (state, action) { // do something? return reducer(state, action); } } 

Vous l'utilisez comme un réducteur normal:

 export default combineReducers({ something: optimistic(something) // wrap "something" reducer }) 

À l'heure actuelle, il passe l'état et l'action au reducer qu'il enveloppe, mais il peut aussi se rappeler des actions:

 function optimistic(reducer) { return function (state = { history: [] }, action) { // do something with history? return { history: [...state.history, action], present: reducer(state.history[state.history.length - 1], action) }; } } 

Maintenant, il accumule toutes les actions dans le domaine de l' history .

Encore une fois, cela n'est pas très utile en soi, mais vous pouvez probablement voir comment vous pouvez implémenter un réducteur d'ordre supérieur qui:

  • Surveille les actions asynchrones en attente par leurs identifiants et commence à enregistrer l'historique lorsqu'elle voit une action avec un status: 'request' ;
  • Quand il reçoit une action avec status: 'done' , réinitialise l'historique;
  • Quand il reçoit une action avec status: 'fail' , ajuste l'historique pour ne pas inclure l'action initiale avec l' status: 'request' et ré-exécute le réducteur pour recalculer l'état actuel comme si la demande ne s'est jamais produite.

Bien sûr, je n'ai pas fourni la mise en œuvre, mais cela devrait vous donner une idée de la façon d'implémenter des mises à jour optimistes de manière Redux.

Mise à jour: selon le commentaire de l'OP, redux-optimist semble faire exactement cela.