FluxxorとReact RouterでFluxのサンプル作った

作ったプロジェクト

github.com

構成

Fluxxor

React Router

React.js

Scala

Play 2.4

Slick 3.0

Fluxとは

Fluxとはアーキテクチャの名前。React.jsはFluxアーキテクチャのViewの実装にあたる。

以下geta6さんのスライドがわかりやすかった。各コンポーネントの説明もされている。

facebookによるfluxの説明。

facebook.github.io

Fluxxor版の全体像。

http://fluxxor.com/images/flux-simple.png

今回は上記に加えてReact Routerを使った。

ルーターの設定

https://github.com/saito400/play2.4-flux-demo/blob/master/app/views/routes.jsx

var React = require("react"),
    Router = require("react-router"),
    Route = Router.Route,
    DefaultRoute = Router.DefaultRoute;

var Navi = require("./common/components/navi_view.jsx"),
    TodoType = require("./todo/components/todo_type.jsx"),
    Todo = require("./todo/components/todo.jsx");

var routes = (
  <Route handler={Navi} name="home" path="/">
    <Route handler={Todo} name="todo" path="/todo" />
    <Route handler={TodoType} name="todo-type" path="/todo-type" />
  </Route>
);

module.exports = routes;

ビルド

JSXファイルはそのままブラウザで実行できない為、JavaScriptに変換する必要がある。

React.jsのブログでアナウンスされている通り、react-tools と JSTransformが廃止され、今後はJSXはBabelでコンパイルする形になる。なので今回はBabelを利用した。

またCommonJS方式のモジュール管理の解決の為、Browserifyを利用し、タスクランナーにgulpを使った。

facebook.github.io

https://github.com/saito400/play2.4-flux-demo/blob/master/gulpfile.js

var browserify = require('browserify');
var babelify = require('babelify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var buffer     = require('vinyl-buffer');
var sourcemaps = require('gulp-sourcemaps');
//var uglify = require('gulp-uglify') // comment out for now because it takes too much time
var watchify   = require('watchify');
var handleErrors = require('./handleErrors');

gulp.task('build', function() {
    return watchify(browserify({ entries: './app/views/app.jsx', debug: true }, watchify.args))
        .transform(babelify)
        .bundle()
        .on('error', handleErrors)
        .pipe(source('bundle.js'))
          .pipe(buffer())
          .pipe(sourcemaps.init({ loadMaps: true  }))
//          .pipe(uglify())
          .pipe(sourcemaps.write('./'))
        .pipe(gulp.dest('./public/javascripts/'));
});

gulp.task('watch', function(){
  gulp.watch('./app/**/*.jsx', ['build']);
});

https://github.com/saito400/play2.4-flux-demo/blob/master/package.json

{
  "name": "play2.4demo",
  "version": "1.0.0",
  "description": "Demo application of play 2.4 and slick 3",
  "main": "index.js",
  "directories": {
    "test": "test"
  },
  "scripts": {
    "build": "$(npm bin)/browserify --debug app/views/app.jsx -t babelify -o public/javascripts/bundle.js",
    "watch": "gulp watch"
  },
  "author": "",
  "license": "",
  "devDependencies": {
    "babelify": "^6.1.2",
    "browserify": "^10.2.4",
    "fluxxor": "^1.6.0",
    "gulp": "^3.9.0",
    "gulp-notify": "^2.2.0",
    "gulp-sourcemaps": "^1.5.2",
    "gulp-uglify": "^1.2.0",
    "gulp-util": "^3.0.6",
    "lodash": "^3.10.0",
    "react": "^0.13.3",
    "react-router": "^0.13.3",
    "tcomb-form": "^0.4.8",
    "vinyl-buffer": "^1.0.0",
    "vinyl-source-stream": "^1.1.0",
    "watchify": "^3.2.3"
  }
}

開発中は rpm run watch を実行し、jsxファイルに変更があったら自動でコンパイルされるようにした。

BabelがES6のトランスパイラなので、ついでにES6のアロー関数を使った。

ES6のアロー関数

mapはこんな感じで書ける。

var options = this.state.todoTypes.map(x => <option value={x.id}>{x.title}</option>);

filterはこんな感じ

this.todoTypes = this.todoTypes.filter(x => x.id != id);

感想

コードの記述量は結構多い。ただ以下twadaさんのツイートにあるように、複雑な設計でも対応できるように感じた。

あと以下naoyaさんのスライドにある通り、記述量は多くなるけどブラックボックス化しにくいと思うので保守は比較的楽だと思う。

TODO

サーバサイド

Play 2.4とSlick 3.0を使った。

あとで何か書く。

Testing

後で調べる。

validation

以下のようにするのが良いらしいだけどまだ試してない。後で試す。

qiita.com

間違ってる所とかあったら教えてください。