Je cherche un moyen d'envoyer plusieurs actions redux dans une seule épopée de redux-observable
middleware.
Supposons que j'ai suivi Epic. Chaque fois que l'événement SEARCH
se produit, Epic charge les données du backend et envoie RESULTS_LOADED
action.
searchEpic = (action$) =>
action$
.ofType('SEARCH')
.mergeMap(
Observable
.fromPromise(searchPromise)
.map((data) => {
return {
type: 'RESULTS_LOADED',
results: data
}
})
)
Supposons maintenant que j'ai besoin d'envoyer une action supplémentaire lorsque le searchPromise
est résolu.
La façon la plus simple de le faire semble avoir une deuxième épopée qui écoutera RESULTS_LOADED
et envoyer la deuxième action. Ainsi:
resultsLoadedEpic = (action$) =>
action$
.ofType('RESULTS_LOADED')
.map(({results} => {
return {
type: 'MY_OTHER_ACTION',
results
}
})
Dans cet exemple simple, c'est assez simple. Mais lorsque les épopées grandissent, j'ai tendance à me retrouver avec beaucoup d'actions redux dont le seul but est de déclencher d'autres actions. De plus, une partie du code rxjs doit être répétée. Je trouve ça un peu moche.
Donc, ma question: existe-t-il un moyen d'envoyer plusieurs actions redux dans une seule Epic?
Il n'est pas nécessaire que vous fassiez un rapport entrée/sortie de un pour un. Vous pouvez donc émettre plusieurs actions en utilisant mergeMap
(alias flatMap
) si vous devez:
const loaded = (results) => ({type: 'RESULTS_LOADED', results});
const otherAction = (results) => ({type: 'MY_OTHER_ACTION', results});
searchEpic = (action$) =>
action$
.ofType('SEARCH')
.mergeMap(
Observable
.fromPromise(searchPromise)
// Flattens this into two events on every search
.mergeMap((data) => Observable.of(
loaded(data),
otherAction(data))
))
)
Notez que tout opérateur Rx qui accepte un observable peut également accepter une promesse, un tableau ou un itérable; les consommer comme s'ils étaient des flux. Nous pourrions donc utiliser un tableau à la place pour le même effet:
.mergeMap((data) => [loaded(data), otherAction(data)])
Lequel vous utilisez dépend de vos préférences de style personnel et de votre cas d'utilisation.
Ou peut-être que vous avez trois actions,
API_REQUEST, API_RUNNING, API_SUCCESS,
searchEpic = (action$) =>
action$
.ofType('API_REQUEST')
.mergeMap((action) => {
return concat(
of({type: 'API_RUNNING'}),
Observable.fromPromise(searchPromise)
.map((data) => {
return {type: 'API_SUCCESS', data};
}),
);
});