web-dev-qa-db-ja.com

redux-observable-単一のエピックで複数のreduxアクションをディスパッチします

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アクションをディスパッチする方法はありますか?

31
dotintegral

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)])

どちらを使用するかは、個人のスタイル設定とユースケースによって異なります。

33
paulpdaniels

または、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}; 
        }),
    );
});
1
Qiang