Redux-sagaで非同期処理を行う
サーバサイドをやることが多くviewを用意するにしてもテンプレートエンジンを使って書く程度しかなかったので仕事で久しぶりにReactとReduxとSagaを使ってみて思い出すのに苦心をした。これを機に設計をして簡単なアプリケーションを作ろうと思う。題材は野球にしようかな
一旦やったことを箇条書きでポイントを書いておこう
要件
アプリケーションURLに特定のxx_idというパラメータが付されたとき、外部APIに対してリクエストを送り(foo.com/bar?xx_id=100
)、レスポンス結果に含まれる画像を画面に表示する
やること
sagaを使う
パラメータを読み取って画像を表示させるまでの処理はすべてredux-sagaを使って非同期処理として扱う。
対象のcomponent・containerを確認する
対象のコンテナを確認したら、sagaで書いた処理を実行するためにReducerとActionを定義して、mapStateToProps
でstoreにActionをdispatchする処理を書く。
storeには新たにxxUrlLoading
というプロパティをboolean型で追加し、APIのレスポンスが返ってくるまでLoadingコンポーネントを表示する。
覚書
パラメータをどう取得するか
Google検索するとReactRouter使おうって初めに出てくると思うのですが、this.props.document.location.search
みたいにpropsでlocationの情報を渡して取得しました
saga
takeLatestは並べた関数の順に最新の情報を更新していくのか。
call
sagaでAPI呼び出しをするときはcallファンクションを使う。
const apiResponse = yield call(Api)
パラメータをpayloadで取得して、payloadの一部だけパラメータに使いたいとき
const xx_id = payload.xx_id const apiResponse = yield call(fooApi, { xx_id })
(fooApiはmodel層で定義して、引数はオブジェクト形式で定義していると想定してください)
これでxx_id=xx_id
というパラメータがAPIに渡せる
関数をgeneratorで定義するわけ
JavaScriptはシングルスレッドで実行されるので複数のタスクを同時に並列に行うということが難しい。
async/awaitだと処理キャンセルができないけど, generatorだとyieldを使って関数の実行を一時的に停止できて、必要なときに戻ってきて返り値を利用することができる。