redux-observable
ミドルウェアの単一のEpicで複数のreduxアクションをディスパッチする方法を探しています。
次のEpicがあると仮定しましょう。 SEARCH
イベントが発生するたびに、Epicはデータをバックエンドからロードし、RESULTS_LOADED
アクションをディスパッチします。
searchEpic = (action$) =>
action$
.ofType('SEARCH')
.mergeMap(
Observable
.fromPromise(searchPromise)
.map((data) => {
return {
type: 'RESULTS_LOADED',
results: data
}
})
)
ここで、searchPromise
が解決されたときに追加のアクションをディスパッチする必要があると仮定しましょう。
そうする最も簡単な方法は、RESULTS_LOADED
をリッスンし、2番目のアクションをディスパッチする2番目のエピックがあるようです。そのようです:
resultsLoadedEpic = (action$) =>
action$
.ofType('RESULTS_LOADED')
.map(({results} => {
return {
type: 'MY_OTHER_ACTION',
results
}
})
この単純な例では、非常に簡単です。しかし、Epicsが成長するとき、私は自分自身が他のアクションをトリガーすることを唯一の目的とする多くのreduxアクションを持っていることに気付く傾向があります。さらに、rxjsコードの一部を繰り返す必要があります。これは少しいです。
それで、私の質問:単一のEpicで複数のreduxアクションをディスパッチする方法はありますか?
1対1のイン/アウト比を作成する必要はありません。したがって、必要な場合は、mergeMap
(別名flatMap
)を使用して複数のアクションを発行できます。
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))
))
)
Observableを受け入れるRx演算子は、Promise、Array、またはIterableも受け入れることができることに注意してください。ストリームであるかのようにそれらを消費します。したがって、同じ効果のために配列を代わりに使用できます。
.mergeMap((data) => [loaded(data), otherAction(data)])
どちらを使用するかは、個人のスタイル設定とユースケースによって異なります。
または、3つのアクションがある場合、
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};
}),
);
});