b

Redux-sagaで非同期処理を行う

サーバサイドをやることが多くviewを用意するにしてもテンプレートエンジンを使って書く程度しかなかったので仕事で久しぶりにReactとReduxとSagaを使ってみて思い出すのに苦心をした。これを機に設計をして簡単なアプリケーションを作ろうと思う。題材は野球にしようかな

一旦やったことを箇条書きでポイントを書いておこう

要件

アプリケーションURLに特定のxx_idというパラメータが付されたとき、外部APIに対してリクエストを送り(foo.com/bar?xx_id=100)、レスポンス結果に含まれる画像を画面に表示する

やること

sagaを使う

パラメータを読み取って画像を表示させるまでの処理はすべてredux-sagaを使って非同期処理として扱う。

対象のcomponent・containerを確認する

redux.js.org

対象のコンテナを確認したら、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で定義するわけ

developer.mozilla.org

JavaScriptはシングルスレッドで実行されるので複数のタスクを同時に並列に行うということが難しい。

async/awaitだと処理キャンセルができないけど, generatorだとyieldを使って関数の実行を一時的に停止できて、必要なときに戻ってきて返り値を利用することができる。

github.com