3
votes

Comment écouter le flux d'action Redux dans le composant

Je travaille sur une application React qui utilise l'architecture suivante:

  • redux
  • typesafe-actions
  • redux-observable

Ma question est la suivante: comment puis-je exécuter une action d'interface utilisateur sur une action redux spécifique?

Par exemple, supposons que nous ayons les actions asynchrones suivantes définies avec typesafe-actions code>:

import { Actions } from '@ngrx/effects';

@Component(...)
class SomeComponent implements OnDestroy {
    constructor(updates$: Actions) {
        updates$
            .ofType(PostActions.SAVE_POST_SUCCESS)
            .takeUntil(this.destroyed$)
            .do(() => /* hooray, success, show notification alert ect..             
            .subscribe();
    }

}

Un Epic recherchera listTodo.request () et enverra l'appel API, puis convertira la réponse en listTodo.success () action. Ensuite, le réducteur de redux sera déclenché par l'action listTodo.success () et stockera la liste de tâches dans le magasin de redux.

Dans ce paramètre, supposons que je veuille faire les choses suivantes dans un composant:

  • envoyer une action listTodo.request () pour récupérer toutes les actions
  • Une fois la requête asynchrone terminée (c'est-à-dire après l'apparition de l'action listTodo.success () dans le flux d'actions), redirigez l'interface utilisateur vers un deuxième chemin

Ma question est donc la suivante: comment pourrais-je regarder le flux d'action et réagir à l'action listTodo.success () ?

MISE À JOUR: Pour éviter d'être trop précis, nous pouvons penser à un autre cas. Je veux simplement afficher une alerte avec window.alert () après que listTodo.success () apparaisse dans le flux d'actions. Ou simplement console.log () , ou tout ce qui change l'état local (au lieu de l'état redux global). Existe-t-il un moyen de mettre en œuvre cela?

UPDATE 2: Il y a une question similaire ici , mais pour Angular w / ngrx. Ce que je veux faire est exactement la chose décrite dans le post ci-dessus, mais de manière React / redux-observable:

export const listTodo = createAsyncAction(
  'TODO:LIST:REQUEST',
  'TODO:LIST:SUCCESS',
  'TODO:LIST:FAILURE',
)<void, Todo[], Error>();


7 commentaires

Comment faites-vous la navigation dans votre application? Utilisez-vous un routeur basé sur Redux comme connected-react-router ?


@Harald Je ne veux pas que cette question soit trop précise. Je sais que si la route est stockée en tant qu'état redux, ce problème peut être résolu. Et si, disons, je veux simplement afficher une boîte de dialogue avec window.alert () après que listTodo.success () est observé?


Ensuite, créez une nouvelle épopée qui surveille listTodo.success () , effectuez un effet secondaire avec action $ .tap (() => {window.alert ()}) puis ignoreElements ()


Merci @Harald. Puis-je faire cela (créer une épopée) dans un composant?


Vous devez utiliser combineEpics () pour combiner tous les Epics de votre application et l'exécuter avec epicMiddleware . Voir redux-observable.js.org/docs/basics/SettingUpTheMiddleware.h‌ tml comment configurer correctement redux-observable


@Harald J'ai commencé à comprendre votre première question. La route devrait probablement être un état global et la modification de la route n'est pas quelque chose dont un composant devrait s'inquiéter. J'essaie de déplacer plus de logiques dans Epics et de voir si je peux résoudre tous les problèmes.


Bonne chance! C'est un peu délicat au début, mais cela deviendra plus facile très rapidement. Et puis les épopées seront un bon moyen d'encapsuler la logique et de réduire l'état global.


3 Réponses :


0
votes

Avec redux, les composants sont mis à jour en fonction de l'état.

Si vous souhaitez mettre à jour un composant en fonction d'une action, mettez à jour l'état dans le réducteur, tel que la définition de {... state, success: true} dans le réducteur. De là, vous lisez simplement l'état dans votre composant comme vous le feriez normalement et si l'état change en succès, vous affichez votre fenêtre.


3 commentaires

Merci @ ralph-ritoch pour la solution. J'ai un peu l'impression que ce serait moins résistant aux erreurs - que se passe-t-il s'il y a d'autres actions qui mettent également à jour l'état de succès ? que se passe-t-il si l'action «demande» asynchrone d'origine est émise deux fois et que l'ordre des actions «succès» successeur ne peut être garanti?


@charlee pour plusieurs états de réussite, vous leur donnez simplement leurs propres noms, tels que loginSuccess, fetchUserSuccess, peu importe. Je stocke régulièrement l'état de redux dans mon composant.Ainsi, lorsque je reçois les mises à jour d'état de l'observable, je peux vérifier si l'état a changé ou non, si le succès est émis deux fois, il ne s'affiche qu'une seule fois.


@charlee si vous avez besoin de synchroniser plusieurs résultats avec un composant, je peux voir la possibilité de maintenir un tableau dans votre état qui a quelque chose comme {success: boolean, id: string} et de remplir id avec une valeur aléatoire ou unique. Je ne peux pas penser à trop de fois où cela serait nécessaire, mais il est possible d'avoir un état de redux de file d'attente.



0
votes

Peut-être un peu en retard mais j'ai résolu un problème similaire en créant un petit module npm. Il vous permet de vous abonner et d'écouter les actions redux et exécute la fonction de rappel fournie dès que le changement d'état est terminé. L'utilisation est la suivante. Dans votre hook componentWillMount ou componentDidMount:

 subscribeToWatcher(this,[
      {  
        action:"SOME_ACTION",
        callback:()=>{
          console.log("Callback Working");
        },
        onStateChange:true
      },
    ]);

Une documentation détaillée peut être trouvée à https://www.npmjs.com/package/redux-action-watcher


0 commentaires

0
votes

J'ai l'impression qu'un dialogue devrait être un effet secondaire, alors vous les mettriez dans des épopées


0 commentaires