FluxxorとReact RouterでFluxのサンプル作った
作ったプロジェクト
構成
Fluxxor
React Router
React.js
Play 2.4
Slick 3.0
Fluxとは
Fluxとはアーキテクチャの名前。React.jsはFluxアーキテクチャのViewの実装にあたる。
以下geta6さんのスライドがわかりやすかった。各コンポーネントの説明もされている。
facebookによるfluxの説明。
Fluxxor版の全体像。
今回は上記に加えて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を使った。
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さんのツイートにあるように、複雑な設計でも対応できるように感じた。
React でクライアントサイドのプログラミングパラダイムがぐっとシンプルになり、破綻せずに多様な要件に挑戦できるようになった。結果として管理すべき複雑さは「おかわり」され、結局プログラミングの複雑さはコントロールできる限界まで増える (Excel に近づいてゆく画面を見ながら)
— Takuto Wada (@t_wada) April 2, 2015
あと以下naoyaさんのスライドにある通り、記述量は多くなるけどブラックボックス化しにくいと思うので保守は比較的楽だと思う。
TODO
サーバサイド
Play 2.4とSlick 3.0を使った。
あとで何か書く。
Testing
後で調べる。
validation
以下のようにするのが良いらしいだけどまだ試してない。後で試す。
間違ってる所とかあったら教えてください。