2016.07.20
React.jsアプリケーションのFluxアーキテクチャを調べてみた
最近、関わったプロジェクトがReactを使っていますが、自分は今回Reactをはじめて使うので、Reactを用いたアプリケーションアーキテクチャFluxを調査してみました。今回の記事で、Fluxアーキテクチャと実際の実装について調べた内容を書きたいと思います。
Fluxとは
Reactを用いたアプリケーションアーキテクチャ
Facebookが提唱したSmalltalk MVCの焼き直し
データが一方通行へ流れるようにするアーキテクチャ
ウェブUIについてそれを適応する
Fluxをインストールすればレールに乗れる
調査するため、自分のCentos7サーバに以下の手順でFacebookのTodoMvcアプリケーションの開発環境を構築しました。
ソースコード
https://github.com/facebook/flux
NodeJsのインストール
$ sudo yum install epel-release $ sudo yum install nodejs $ node -v
ついでにnpmをインストールするのであれば
$ yum install -y npm --enablerepo=epel
GithubからCloneしたソースコードの直下に以下のコマンドを実行することで(package.jsonに定義される)必要なライブラリを全部インストールできます。とても便利です。
# npm install
早速、Reactアプリケーションをスタートします
# npm start > [email protected] start /var/www/html/todomvc > watchify -o js/bundle.js -v -d js/app.js 2906788 bytes written to js/bundle.js (2.42 seconds)
アプリケーションにアクセスしてみると、Todo管理アプリがちゃんと動いていることを確認できました。
ここで、アプリケーションの開発環境構築が完了しました。ソースコードを調査しながらFluxのアーキテクチャーを確認します
Fluxアーキテクチャ
以下はFacebookがFluxの一方通行へ流れるについて説明する図です
実際のソース構成を確認しますと、Action、Store、Component(React)の3つが存在し、それを繋ぐのがEventEmitter(or Dispatcher)です。StoreはActionを監視し、Actionが持つEventEmitterを監視します。ComponentはActionを呼び、ActionがEventを発行します。ComponentはStoreの変更を監視し、Store自身がEventEmitterとして動くイメージです。
![]() |
![]() |
概念 | 説明 | 備考 |
---|---|---|
EventEmitter | イベントリスナの登録/処理ができるモジュールを作る。Flux内のイベントも全てディスパッチャから一方向に流れる。 |
#on : イベントtypeに対してコールバックの登録 #emit: イベントtypeに登録されたコールバックの実装 #off : イベントtypeに対してコールバックの登録解除 |
ディスパッチャ(Dispatcher) | アプリの中央のハブで、全てのデータの流れを管理する | Store内のデータを操作する処理を行い、その後で 関連するViewのステータスを更新する処理を実行(イベントの発火)する |
ストア(Store) |
EventEmitterを継承する。あるイベントがやってきたら、State(内部の状態)を更新し、 内部Stateを更新したら”CHANGE”イベントを発行する |
MVCのモデルと同じ。 |
アクション(Action) | あるイベントを発行する関数。アプリケーションに広げるために、イベントをディスパッチャへと送る | Actionには “actionType”プロパティを持たせて、区別できるようにする |
Component |
・Storeの変更を監視する(Listen) ・Viewの更新 必要なデータを全て手に入れてしまえば、画面に表示する ・ユーザーイベントの受付 Clickされた◯◯するといった動作 |
Todoの更新機能でFluxの実装を確認する
Todo一覧画面にて、ユーザーがTodoを更新すると、TodoActionsのupdateTextを実行する
input = <TodoTextInput className="edit" onSave={this._onSave} <---★イベントの設定 value={todo.text} />; /** * Event handler called within TodoTextInput. * Defining this here allows TodoTextInput to be used in multiple places * in different ways. * @param {string} text */ _onSave: function(text) { TodoActions.updateText(this.props.todo.id, text); <--アクションを呼ぶ this.setState({isEditing: false}); },
TodoActionにてTodoStoreに更新イベントを通知
var TodoActions = { /** * @param {string} id The ID of the ToDo item * @param {string} text */ updateText: function(id, text) { AppDispatcher.dispatch({ actionType: TodoConstants.TODO_UPDATE_TEXT, <---TodoStoreのほうにDispatch id: id, text: text }); }, }
TodoStoreのほうは、データ更新し、ビューを更新するため、Componentに通知する
case TodoConstants.TODO_UPDATE_TEXT: text = action.text.trim(); if (text !== '') { update(action.id, {text: text}); <---データストアを更新 TodoStore.emitChange(); <---Todo画面にデータを更新するため、TodoAppのほうに通知 } break;
TodoApp ComponentがTodoStoreからさ最新データを取得し、ビューを更新する
var TodoApp = React.createClass({ componentDidMount: function() { TodoStore.addChangeListener(this._onChange); <--- TodoStoreの変更をListen }, /** * 画面表示処理 * @return {object} */ render: function() { return ( <div> <Header /> <MainSection allTodos={this.state.allTodos} areAllComplete={this.state.areAllComplete} /> <Footer allTodos={this.state.allTodos} /> </div> ); }, /** * Event handler for 'change' events coming from the TodoStore */ _onChange: function() { this.setState(getTodoState()); <--- 変更があるときは、TodoStoreから全件を取得する } /** * Retrieve the current TODO data from the TodoStore */ function getTodoState() { return { allTodos: TodoStore.getAll(), areAllComplete: TodoStore.areAllComplete() }; }
APIの実行はどこで実装するのか
FluxアーキテクチャでAction CreatorsでAPIを実行しますが、ビューがStoreから最新データを取得するので、APIの実行はStore内から通信してStoreで完結しても良いと思われます。
まとめ
いかがでしょうか?Reactを用いたアプリケーションアーキテクチャFluxについて調査しました。Fluxアーキテクチャにいろいろな要素がありますが、実際のソースコードを確認したらすごくデータの流れなども把握しやすく見通しの良いコードになるかと思います。
参考
https://facebook.github.io/flux/docs/overview.html
http://www.pupha.net/archives/3218/
http://azu.github.io/slide/react-meetup/flux.html
次世代システム研究室では、グループ全体のインテグレーションを支援してくれるアーキテクトを募集しています。アプリケーション開発の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いします。
皆さんのご応募をお待ちしています。
グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。
Follow @GMO_RD