#daiizメモ

Scrapboxに夢中

React-Redux 入門日記

日曜日と月曜日を使ってReact-Reduxに入門したお話.

勉強中のコードなのであまり参考にならないと思うが,週末の成果物としてGitHubリポジトリ /daiz713/MyExpressAppに置いといた.アプリのフレームワークにNode.jsのExpressを使って,ViewにReact+Reduxを採用している.データベースは以前使ったことにある MongoDB にしようと思ったけれど Google Cloud Datastore が Google App Engine 以外のウェブアプリからも呼び出せることを知ったので Datastore にした.(Datastoreは今回の範囲ではまだ使わない)

リポジトリのREADMEに書いてある /album というのが一番新しい練習作品で,最近Gyazoった写真を表示するミニアルバムアプリ<Album />となっている.Reactコンポーネント <Album /> 内には,いくつかコンポーネントが内包されているが,メインとなるのは <GyazoImage /><GyazoImageList /> で,これらに渡る props を更新していくことで画面の描画内容を変化させられる.ユーザーのクリックイベントなどに基いて ActionCreator が Action (単なるJSオブジェクト) を発行し,Reducer と呼ばれる関数が Action の type に応じて次にセットすべき state (props?) を返す.これに基いてコンポーネントの render 関数が差分を描画する.やっぱりこの仕組みは面白い.

Image

ここまで理解してくると,非同期でない処理は書けそうな気がしてきて,やってみると予想以上にすんなりと実際に書ける.しかし,今回のお題はGyazoアルバムを作ることなのでどこかで Gyazo API を呼ぶ必要がある.適当に呼んでも動きそうだけど,それだと美しい機構が壊れてしまうので色々調べてみる.すると Action と Reducer の間に噛ませる Middleware である react-thunk を使うと良いらしいことが分かった.これを用いると,ウェブAPI呼び出し〜読み込み完了の状況に応じて非同期的に Action を発行 (dispatch) する fetchGyazoImagesAsync のようなActionCreatorが書けるようになる.<GyazoImageList /> が componentDidMount になったときに関数fetchGyazoImagesAsyncを呼び出すことで,画面表示のタイミングで自然とAPIコールが始まった.これまであまり意識していなかったが,APIを呼び出してから目的達成するまでには,以下のような状態が考えられる.

  • 取得中
    • -> 成功
    • -> 失敗

これらの情報を詰め込んだ Action を逐一発行すれば,ロード中のアニメーションも作りやすいかもしれない.
無事に画像リストの取得が完了したら,<GyazoImageList /> 内に <SquareThumbnail /> を新規生成していく.これにクリックイベントを仕掛けたいときは,GyazoImageList の props に予めhandler関数を与えておき,SquareThumbnail でその関数を参照させる,というふうにやっている (これが正しい方法であるかはまだ自信がない).一番上層まで参照が伝わると,関数 mapDispatchToProps で紐付けていた ActionCreator が発動する.この関数が発行する Action によって,写真プレビュー用のReactコンポーネントである <GyazoImage /> の props が更新されて,画面も更新される.


実際にクリックして動かしている様子はこんな感じで,Chrome Devtool である React Developer Tools を入れておくと,クライアントサイドで構築されたReactコンポーネントの props や store の中身などを逐一確認できる.<SquareThumbnail />要素をクリックすると <GyazoImage /> の内容が更新される.DevToolでは,更新された箇所が緑でハイライトされる.


ここまでAlbumアプリを書いてきたけれど

  • props と state の違いがいまひとつ分からない
  • コンポーネント間で props 受け渡しリレーみたいなことが起こっていて鬱陶しいのだけど,こんなもんなのだろうか.
  • props と state を紐付けている(?) mapStateToProps の書き方がだいぶ面倒くさいけれど,本当に現状の書き方で合っているのか

のような疑問が残った.次回以降の練習作品で解決したい.

参考文献