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
となります。要件にあわせてmergeMap
はswitchMap
やconcatMap
、exhaustMap
に置き換えます。
mergeMap
・switchMap
・concatMap
・exhaustMap
の違いの詳細解説は【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_SUCCESS
やGET_TODOS_FAILURE
のAction Typeを発行します。
APIリクエストが成功した場合はsetTodos
によってAPIで取得したTodoリストがStateに保存されます。
上記のEpicを利用したTodoアプリのサンプルコードはnishina555/redux-observable-todoapp-with-async-stateで公開しています。
さいごに
Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!