【redux-observable】Epicで複数のActionを発行する方法

JavaScript

Action inとAction outが1対1の場合

以下はGET_TODOS_REQUESTというAction Typeの発行をトリガーに、APIへのリクエストとsetTodosというAction Creatorを実行するEpicの例です。

const getTodosEpic: Epic<GetTodosActions | TodoActions> = (action$) =>
  action$.pipe(
    ofType(GetTodosType.GET_TODOS_REQUEST), // GET_TODOS_REQUESTというAction Typeが発行されたら以下を実行
    mergeMap(() => // メッセージを受け取り、新たなストリーム(Observable)を作成する
      from(axios.get("http://localhost:4000/todos")) // PromiseオブジェクトからObservableを生成
        .pipe(
          map((response) => setTodos(response.data)) // APIの結果をsetTodosを利用してStateにセットする
        )
    )
  );

上記のEpicは、コンポーネントがTodoリストを返すAPIにリクエストしたいことを検知し、APIから取得したTodoリストをReactアプリケーションのStateにセットする役割を果たします。

setTodosが返すAction TypeをSET_TODOSとすると、以下のEpicのAction in(GET_TODOS_REQUEST)とAction out(SET_TODOS)の関係は1対1になります。

上記のEpicを利用したTodoアプリのサンプルコードはnishina555/redux-observable-todoappで公開しています。

redux-observableを利用したTodoアプリケーションの具体的な実装の手順についてはTodoアプリで理解するredux-observableによる非同期処理の実装方法で紹介しています。

Action inとAction outが1対多の場合

GET_TODOS_REQUESTを受け取った際、StateのTodoリストを更新するSET_TODOSだけでなく、APIリクエストの結果(成功 or 失敗)をStateに記録するアクションもあわせて発行したいと考えたとします。
このとき、Action inとAction outの関係は1対多になります。

Epicで複数のアクションを発行する場合は当該アクションを配列にセットします。
Action outが1つの場合Operatorはmapを利用していましたが、Action outが複数の場合はmergeMapとなります。要件にあわせてmergeMapswitchMapconcatMapexhaustMapに置き換えます。
mergeMapswitchMapconcatMapexhaustMapの違いの詳細解説は【RxJS】concatMap, mergeMap, switchMap, exhaustMapの違いで紹介しています。

const getTodosEpic: Epic<GetTodosActions | TodoActions> = (action$) =>
  action$.pipe(
    ofType(GetTodosType.GET_TODOS_REQUEST),
    mergeMap(() =>
      from(axios.get("http://localhost:4000/todos"))
        .pipe(
          mergeMap((response) => // 複数のアクションは mergeMap(switchMap, concatMap)で発行する
            [setTodos(response.data), getTodosSuccess()] // 発行したいActionが複数ある場合は配列にセットする
          ),
          catchError((error: Error) => { // APIリクエストが失敗(Promise.reject)した場合の例外処理
            console.log(error);
            return of(getTodosFailure());
          })
      )
    )
  );

上記のEpicは、APIリクエストの結果に応じてGET_TODOS_SUCCESSGET_TODOS_FAILUREのAction Typeを発行します。
APIリクエストが成功した場合はsetTodosによってAPIで取得したTodoリストがStateに保存されます。

上記のEpicを利用したTodoアプリのサンプルコードはnishina555/redux-observable-todoapp-with-async-stateで公開しています。

さいごに

Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!

参考