yutaponのブログ今回はFluxアーキテクチャについて学びたいと思ったので、TodoMVCを題材に写経してみました。構成・ロジックは参考にしつつ、ES6構文で書くようにしてます。参考にしたコードはfacebook/fluxのexamplesのコードになります。GitHubhttps://github.com/facebook/flux/tree/master/examples/flux-chat作ったコードはここに置いていて、https://github.com/sskyu/react-flux-todomvc-example/tree/blog-20150427動かすといつものTODOリストが表示されます。Fluxとはおおまかに言うと、MVCアーキテクチャみたいな設計手法のこと。MVCだと3つの責務に分割するところを、Fluxだと大きく4つの責務に分割しています。図を見てもらったほうが早いです。こちらにあるよく見る図を使わせていただきました。次の4つに分割されているように見えます。(React)ここで注目したいのは、例えばActionCreatorsの場合はStoreと直接やりとりせず、ViewまたはActionCreators自身に呼び出され、Dispatcherとやりとりするという風に、処理の流れが単方向に限定されていることです。この考え方に従って設計していくと、処理の流れを掴みやすくなる利点がります。各要素がどのような責務を持っているかは、私が理解した範囲だと次のようになります。ActionCreatorsアプリケーション内のDSLのような、実装とは一つ切り離した抽象的な命令セットを定義する。View(ユーザー)からのアクションと、データを取得・保持するためのAPIアクションがある外部のAPIを叩く時はStoreではなくActionCreators内の責務コードが煩雑化するので外部APIを使う時はApiUtilsを定義すると良いDispatcherActionCreatorsがDispatcherにアクションをpublishするStoreがDispatcherのアクションをsubscribeする実装の量も少ないし冗長かと思うかもしれないけど、実行されるコールバックの順番を制御したりするのに必要Storeリソース管理とロジック部分Dispatcherにpublishされるであろうイベントを購読して、各アクションのハンドリングするシングルトンとして実装し、サーバーと同じデータをローカル内にも保持しておくリソース状態を提供するgetterメソッドは定義してもよいが、リソースを更新するsetterメソッドは提供しないView側から直接リソースを変更できなくする。更新系はDispatcher経由のハンドラで処理する保持しているデータに変更があった場合はEventEmitter経由でchangeイベントを発行するViewUI部分全般を担当ControllerView的なコンポーネントがStoreから描画に必要なデータを受け取り、描画後もデータの変更を監視するデータの変更があった場合は差分だけが部分描画される(virtual-domのおかげ)ユーザからのアクションがあればハンドリングし、必要ならActionCreators経由でデータを操作するControllerView的なコンポーネントというのは、今回の例で言うとcomponents/TodoApp.jsになります。setState()でコンポーネントが持つ状態を最新にしてrender()が走る、といった流れになります。まとめてみるとこんな感じで理解しました。TodoMVC写経してみての所感React(virtual-dom)による描画コストを考えなくても良いプログラミングに感激しました。Storeを見るとわかるのですが、Todoの集合をStore内でしかアクセス出来ない変数に保持して、常にサーバー(実体はlocalStrage)と同じ状態を保つようにしています。ユーザが既存のTodoのテキストを変更すると次のような処理が走ります。変更があったテキストを持つDOMノードのみが再描画される【】の中だけ見ると処理の流れが一方向で秩序がある感じがしますね・・!ポイントはAPIの更新処理を待たずに表示を変更させ、サーバーと同期したらもう一度Viewを更新し直すところです。(ユーザーにいち早くフィードバックを返すためにこのような仕様にしてます。サーバーの更新処理を待って表示したい場合はローディング画面を表示しても良いでしょう。)もしBackboneで描画コストを考慮してやろうとすると、前回の値と比較して変更されている部分だけを更新する・・といったチェックするコードが増えていき、どんどんコードが煩雑化していきます。Reactだとこの辺の描画コストをvirtual-dom任せにできるので、描画コストをあまり考えなくても良くなります。BabelについてBabelがすごく良くて、将来的にjQueryみたいなポジションになって嫌われないか心配。いつの間にかClass構文でクラスのmemberを定義できるようになってました。0みたいなものを加える必要があります。詳しくはこちらを参照して下さい。https://babeljs.io/docs/usage/experimental/Babelを使っていればデフォルトでFlowTypeが使えるのですが、これ使ってしまうとBabelにロックインしすぎてしまう懸念もあったり(手遅れ)。React+Fluxのまだわからないところファイルの命名規則JSX使っているコンポーネントとかは.jsxにする、とかはありかも。見て回ったけど先頭大文字のファイル名で始めるのが多かった。Constantsとかオブジェクトの参照をexportしてるファイルも先頭大文字のものが多く、個人的にはクラス定義をexportしてるやつだけ先頭大文字がいいと思ってたけど、違うのだろうか。しようって明確な決まりがないみたいなので、プロジェクト内でスタイルガイド作って行けば良さそう。完全に独立したコンポーネントならcomponentsディレクトリ以下にフラットに置いてもいいのかな。あるコンポーネントに従属するコンポーネントとかはディレクトリ切りたくなるけど、それによる弊害みたいなのあるのだろうか。大きいものつくってみないと実感わかないところである。TodoStore()みたいにインスタンスの参照を外に出した。アプリケーションがSPAでスマホを対象にする場合、メモリ管理を徹底していく必要があるわけだけど、このままだとインスタンスの参照をどのタイミングで破棄すればよいかわからないことになってる。こちらのスライドを見て、Storeはシングルトンでもいいんだって思ったりしたけど、本当のところはどうなのだろうか。speakerdeck.comStoreManagerみたいなやつを上位に設けてインスタンスの管理をしたほうが良い気がする。それにしてもこのスライド、めっちゃわかりやすい。おわりにReactMeetup#1でazuさんが言ってた気がするけど、Fluxを理解するには実際に書いてみるのが一番ってのは本当だなと思います。一回書いてみると、最初は冗長だと思っていた書き方が秩序を持ち始めることに気づきました。ActionCreatorsがアプリケーションの主役に見えてきます。細かい部分でまだ疑問点があるので、ノウハウをもっと知りたいところ。(1)月別アーカイブスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。