react.jsのjsxファイルをjsに変換してみる
以前作ったもの
reactjsで超単純なTODOアプリを作成してみた - m_shige1979のささやかな抵抗と欲望の日々
これが現在はjsxで作っている。
実際、jsxのほうが作りやすいけどなんかあれかもしれないので分割してみる
ついでにnode.jsの方法で作成
バージョン
react.0.14くらいに変更したかと…
npmでインストールしたら最新ものをとってきたので
npm
jsxからjsへ変換するモジュール
npm install browserify -g
reactとかjquery
npm install react reactify npm install react-dom npm install jquery
分割対応
index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Reactjs-TodoApp</title> </head> <body> <div id="content"></div> <script src="js/app.js"></script> </body> </html>
jsx/app.jsx
var React = require('react'); var ReactDOM = require('react-dom'); var $ = require('jquery'); /** * TodoApp */ var TodoApp = React.createClass({ getInitialState: function() { return {data: []}; }, // コンポーネントがレンダリングされた場合に呼ばれる componentDidMount: function() { this.setState({ data: this.props.data }); }, render: function() { return ( <div className="todoApp"> <h1>TodoApp</h1> <TodoForm onAddSubmit={this.addList} /> <TodoList data={this.state.data} onDelSubmit={this.delList} /> </div> ); }, addList: function(item){ // 取得 var _data = this.state.data; var _data2 = _data.concat([item]); // 更新 this.setState({data: _data2}); }, delList: function(item){ // 取得 var _data = this.state.data; // idが指定の場合は削除 _data.some(function(v, i){ if (v._id == item){ _data.splice(i, 1); } }); // 更新 this.setState({data: _data}); } }); var TodoForm = React.createClass({ onAddListSubmit: function(){ // 値を取得 var _text = ReactDOM.findDOMNode(this.refs.text).value.trim(); if(!_text){ return; } // 値を編集 var _item = { _id: (new Date()).getTime(), text: _text } // 追加処理 this.props.onAddSubmit(_item); // 初期化 ReactDOM.findDOMNode(this.refs.text).value = ''; return; }, render: function() { return ( <form className="todoForm"> <span>タスク:</span> <input type="text" placeholder="入力…" ref="text" /> <input type="button" value="追加" onClick={this.onAddListSubmit} /> </form> ); } }); var TodoList = React.createClass({ render: function() { // 削除ボタン var _btn = this.props.onDelSubmit; // this.props.dataをmap処理で定義 var itemNodes = this.props.data.map(function (item) { return ( <TodoItem dataKey={item._id} onDelListSubmit={_btn}> {item.text} </TodoItem> ); }); return ( <div className="todoList"> {itemNodes} </div> ); } }); var TodoItem = React.createClass({ getInitialState: function() { return { mode: {} }; }, componentDidMount: function() { this.setState({ mode: {} }); }, onItemChange: function(e){ var _checked = ReactDOM.findDOMNode(this.refs.chk).checked; if(_checked === true){ this.setState({ mode: { "text-decoration": "line-through" } }); }else{ this.setState({ mode: {} }); } }, delSubmit: function(){ var _dataKey = $(ReactDOM.findDOMNode(this.refs.dataKey)).attr("data-key"); this.props.onDelListSubmit(_dataKey); ReactDOM.findDOMNode(this.refs.chk).checked = false; this.setState({ mode: {} }); }, render: function() { return ( <div className="todoItem"> <input type="button" value="削除" onClick={this.delSubmit} /> <label> <input type="checkbox" ref="chk" unchecked="unchecked" onChange={this.onItemChange}/> <span data-key={this.props.dataKey} style={this.state.mode} ref="dataKey">{this.props.children}</span> </label> </div> ); } }); var _list = [ ]; ReactDOM.render( <TodoApp data={_list}/>, document.getElementById('content') );
バージョンが変わったのでちょっと修正している
gruntとかは
Gruntfile.js
module.exports = function (grunt) { var pkg = grunt.file.readJSON('package.json'); grunt.initConfig({ browserify : { dev: { options: { debug: true, transform: ['reactify'] }, files: { 'js/app.js': 'jsx/**/*.jsx' } } }, watch : { scripts : { files : ['jsx/**/*.jsx'], tasks : ['browserify:dev'] } } }); Object.keys(pkg.devDependencies).forEach(function (devDependency) { if (devDependency.match(/^grunt\-/)) { grunt.loadNpmTasks(devDependency); } }); grunt.registerTask('default', ['watch']); };
gulpfile.js
var gulp = require('gulp'); var browserify = require('browserify'); var source = require("vinyl-source-stream"); var reactify = require('reactify'); gulp.task('browserify', function(){ browserify('./jsx/app.jsx', { debug: true }) .transform(reactify) .bundle() .on("error", function (err) { console.log("Error : " + err.message); }) .pipe(source('app.js')) .pipe(gulp.dest('./js')); }); gulp.task('watch', function() { gulp.watch('./jsx/*.jsx', ['browserify']) }); gulp.task('default', ['watch']);
うーんなんかこの辺はまだ良くわかっていない
所感
javascriptで書くよりはjsxのほうが助かる場合もある…
問題としてはバグが発生した場合に何が原因かをうまく見つけられるかということかな?
browserifyでnodejsのモジュールをクライアントjsで一部動かせることがわかったのでflux?とかいうのも動かせるか確認したいと思う