LoginSignup
14

More than 5 years have passed since last update.

React+Fluxxor+ajaxでfluxなTODOアプリ

Last updated at Posted at 2015-08-01

Web+DB Pressのvol86と87で伊藤直也さんのReact.js+Fluxの記事があったので勉強してみました。

vol86のReactだけだと外部のAPIとかとの連携のイメージがつきにくかったんですけど、vol87の記事のサンプルを動かしてみてやっと
とはいえまだまだですが汗

やったこと

Reactに慣れてからfluxへという流れです。

まずはTODOアプリを作る

サンプルはこちらに置いておきます。 https://github.com/n0bisuke/react-study/tree/todo-flux

Flux構成のフレームワークであるFluxxorを使って、vol87の記事では紹介してくれています。

早速ですが、実行するとこんな感じです。

Fluxの解説などはWeb+DB Pressを読みましょうw

Fluxxorにajax的な処理を追加してみる

Web+DB Pressの記事では説明が少し割愛されていた部分です

サーバー上にあるjsonデータをHTTPリクエストで取得してTODOリストとして表示させる作りに変えてみます。ちなみに、サンプルはこちらに置いてきます。 https://github.com/n0bisuke/react-study/tree/todo-flux-ajax

非同期通信系の処理はActionを起点にしましょうとのことでActionから処理を追って説明をしてみます。 (ツッコミ歓迎!!)

0. jQuery読み込みとJSONデータ用意

jQueryの$.ajax()を使ってみます。jQueryのロードはindex.html側に書きました。

index.html
<html>
  <head>
    <title>TODOリスト</title>
  </head>
  <body>
    <div id="app-container"></div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script charset="utf-8" src="dest/app.js"></script>
  </body>
</html>

データはこんな感じです。

todos.json
[{
  "text": "ほげ"
 },
 {
  "text": "ふが"
 }
]

ここにapp.jsxの完成系があるのですが、以下で個別に説明してみます。

1. Action(Action Creator)にlaadTodosメソッドを追加

まず、 Actionは定数で定義された、アクションの識別子{value:1}などの入力値に相当するオブジェクトのペアを指すとのことです。ということでLOAD_TODOS_SUCCESSという識別子を定義しておきます。

7行目

app.jsx
/*省略*/

var constants = {
  ADD_TODO:    "ADD_TODO",
  TOGGLE_TODO: "TOGGLE_TODO",
  LOAD_TODOS_SUCCESS: "LOAD_TODOS_SUCCESS" //追記
};

/*省略*/

57行目付近

メソッド内に$.ajax()での処理を記述してきます。
ajax処理の完了時.done()の処理でthis.dispatch()でdataをDispacher経由でStoreに送ります。

app.jsx
/*省略*/

var actions = {
  //追加
  loadTodos: function(){
    $.ajax({
      url: "./todos.json"
    }).done(function(data){
      this.dispatch(constants.LOAD_TODOS_SUCCESS, {data: data});
    }.bind(this));
  },

  /*省略*/

this.dispatch()内の(constants.LOAD_TODOS_SUCCESS, {data: data}の部分がStoreに対して操作を要求するメッセージ(=アクション)となるみたいです。

.bind(this)を書いておかないと動かないので注意!これWeb+DB Press側のコードミスかも。JSのthisの罠。

2. Storeでアクションとメソッドの紐付け(bind)

先ほどのアクションがStoreに送られた際に実行する処理とその紐付けです。

17行目

app.jsx
/*省略*/
var TodoStore = Fluxxor.createStore({
  initialize: function() {
    this.todoId = 0;
    this.todos = {};
    this.bindActions(
      constants.ADD_TODO,    this.onAddTodo,
      constants.TOGGLE_TODO, this.onToggleTodo,
      constants.LOAD_TODOS_SUCCESS, this.onLoadTodosSuccess //追記
    );
  },

  /*省略*/

this.bindActions()で先ほど定義したLOAD_TODOS_SUCCESSのアクションがStoreにメッセージとして送られて来た際のメソッドを紐付けます。ここではonLoadTodosSuccessメソッドに紐付けています。

36行目付近

app.jsx
  /*省略*/

  //追加
  onLoadTodosSuccess: function(payload){
    payload.data.forEach(function(item){
      var id = ++this.todoId;
      var todo = {
        id: id,
        text: item.text,
        complete: false
      };
      this.todos[id] = todo;
    }.bind(this));
    this.emit('change');
  },

  /*省略*/

onLoadTodosSuccessメソッドの中身です。 idをインクリメントしながらデータを追加していく処理になってます。
payloadさっき(61行目){data:data}の部分が送られてきます。

つまり、http通信でGETした内容(todos.jsonの内容そのまま)です。

Action側で非同期処理を書き、処理完了時点のデータをStoreに送り、Storeの中では非同期処理は行わないようにするとデータフローが明確になって良いとのことです。

47行目this.emit('change');と呼んでいます。Storeが管理するデータに変更があったことをViewに伝えてあげます。
これでViewまで伝えてあげたらあとは通常のTODOアプリと同じです。

3. View側でActionCreatorを発火してあげる

1と2で作った処理のトリガーはView側になります。
今回はViewのロード時にこのアクションを実行します。

80行目

app.jsx
  /*省略*/

getInitialState: function() {
    this.getFlux().actions.loadTodos(); //追加: viewの呼び出し時にロード
    return { newTodoText: "" };
  },

    /*省略*/

view側のgetInitialStateメソッド内でloadTodos()を呼び出してあげて、読み込み時にAjaxでデータを取得する処理の完成です。

まとめ

サーバー側の処理を書くのがダルかったのでPOSTでデータ追加とかはやらなかったけど、同じような雰囲気で書けると思います。

Fluxの流れを理解できた気がする...!

次はMilkcocoaと連携してみたいと思います!
http://qiita.com/n0bisuke/items/f28016de82136a2a4d26

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14