React Native に Reduxを加え、ロジックを実装する
概要
React Native入門シリーズその3。 Reduxを導入してAPI通信してViewに引き渡す。
前回: ReactNativeにTypeScriptを導入する - のらねこの気まま暮らし
APIについて
OpenWeather
アプリについて
今回試すことが主軸にあって、 「こういうView」っていう提案まで考えてない。よって実用的ではないものだが、アプリの構成について考える土台として雑に作る。
インタラクション
本来なら、今の天気を取得しつつ予報も出すべきだが前述の通り手抜きで対応する。
- ボタンを押したら、天気の読み込みが始まる。
- 天気の読み込みが完了したら、天気の情報を表示する。
View設計
- 今の天気を取得するボタン
- 天気の状態をそのまま表示
アーキテクチャ
アプリの構造を考えるぞい。
選定
- Redux Way
- Redux Way Arrange
- Ducks
Redux Way系は役割でコードを分ける、Ducksは関心でコードを分ける。
個人的にクライアントの関心はViewの側面から見たActionとアプリ全体から見たStateに分けられると思っていて、そこを密結合することに懸念がある(実際、Vuexでも結構悩んだ)。
今回はReduxについて真剣に考えるより、React Nativeを知ることが目的なので複雑な悩みを抱えたくない。
しかし、Redux Wayは僕の感覚に則さない...
ということで感覚的にしっくり来るようにRedux WayをArrangeする。
Redux Way Arrange
View層
React Componentを配置する。 Container,Presentational,AppRootを管理する。
UseCase層
Viewから入力を受け取り、dispatchのタイミングを制御する。 いざ名乗ってみると違和感しかない。 Containerと対応する。
Action層
ActionCreator。
UserCaseで構築したデータをActionにパッキングする。 ここはもっと隠蔽できると嬉しい。
究極、s2sとか使って自動生成したい。
Store層
Redux Storeの初期化と、Reducerの定義を担う。 Reducer基本的にStoreからしか参照されないしっていうかStoreの一部だよね、の気持ち。
ReducerはViewではなく、アプリ内のドメインと対応する。 Stateはアプリにおける情報のドメイン。
Service層
名前に悩んだけどまあとりあえず。
外部APIとの通信、アプリへの最適化を担う。 だいたい外部APIを使う場合(それが自前で用意したAPIだとしても)要求以上の実装がされがちなので、そういう本質的ではないが必要なことをまとめておく場所。
基本的にUseCaseからしか呼ばれない。
実装フロー
事前想定:
- 天気取得ボタンの作成
- 天気取得のUseCaseの作成
- Reducerの雛形
- OpenWeather API取得の実装
- UserCase内でAPI呼び出し
- weather用のReducerを定義
- ViewにReducerから取得したデータを表示
実際:
- React + Reduxの雛形作成
- ボタンの作成
- 天気取得のUseCaseの作成
- Actionの作成
- Reducerの作成
- 型の定義(Action, State, Props, etc)
- Weather用のReducerを定義
- ここでContantsが必要だと判断
- OpenWeather API取得の実装
- weatherのReducerに実データとローディングフラグを実装
- Viewに読み込み時の処理と天気表示を実装
つまったところ
connect
の実装と型定義Object.assign
の引数の順番間違えた- OpenWeather APIの仕様調査と型定義
モジュールの変化
core
- react-redux
- redux
- @types/react-redux
- @types/redux
service
- axios
- qs
- @types/qs
所感
TypeScriptの警告つぶしが結構面倒だった。 Reducer定義しないといけないことを知った。 OpenWeatherAPIの仕様以外と知らなくて手間取った。 土台ができちゃえばあとは継ぎ足しで行けるかなって思った。 あれ、ReactNativeってなんだっけ?