WEB+DB PRESS Vol.86
- 作者: 結城洋志,沖元謙治,足永拓郎,林健太郎,大竹智也,内田誠悟,伊藤直也,中山裕司,hiroki.o,泉水翔吾,佐藤太一,高橋俊幸,西尾泰和,舘野祐一,中島聡,橋本翔,はまちや2,竹原,麻植泰輔,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2015/04/23
- メディア: 大型本
- この商品を含むブログを見る
第12回 React によるフロントエンド開発の変革
- State - コンポーネントの状態管理
- setState() とコンポーネントの再描画
- DOM操作についてはついては一切コードを書いて無い
- Virtual DOM
- JSX と Virtual DOM
- React アプリケーションの基本設計
- Props - 親子コンポーネント間のインターフェイス
- Props は不変に
- 子は値を使うだけで、管理するのは親であることを基本原則とする
- 子から親への処理の委譲
- react-tools による JSX のビルド
- jsx ファイルを js ファイルに変換
- 変換後は普通の js ファイルなので、JSXTransformer はもう必要ない
% jsx -x jsx --watch src/ dest/
- Browserify + reactify によるビルド
- Browserify は CommonJS スタイルで分割された JavaScript モジュール群を
依存関係を考慮しながら1つのファイルにまとめてあげてバンドルするツール
- CommonJS スタイルは module.exports でオブジェクトや関数をエクスポートし
require でそれをロードする Node.js でおなじみの仕組み
% npm i -g browserify
% npm i react
% npm i reactify
% ulimit -n 1024
% browserify -t reactify src/app.jsx -o dest/app.js
- ulimit でファイルディスクリプタの最大を増やさないと(デフォ 256 だった)、browserify コマンドでこける
var React = require('react');
var App = React.createClass({
getInitialState: function() {
return {
message: "",
savedMessages: []
};
},
updateMessage: function(message) {
this.setState({ message: message.target.value });
},
saveMessage: function(message) {
console.log(message);
var messages = this.state.savedMessages.concat(message);
this.setState({ savedMessages: messages });
},
render: function() {
return (
<div>
<MessageInput onChange={ this.updateMessage } onSave={ this.saveMessage } />
<Message message={ this.state.message } savedMessages={ this.state.savedMessages } />
</div>
);
}
});
var MessageInput = React.createClass({
_onChange: function(e) {
this.props.onChange(e);
},
_onKeyDown: function(e) {
if (e.keyCode === 13) {
this.props.onSave(e.target.value);
e.target.value = "";
}
},
render: function() {
return <input type="text" onChange={ this._onChange } onKeyDown={ this._onKeyDown} />;
}
});
var Message = React.createClass({
render: function() {
var key = 0;
var messages = this.props.savedMessages.map(
function(message) {
return <li key={ key++ }>{ message }</li>;
}
);
return (
<div>
<p>{ this.props.message }</p>
<ul>{ messages }</ul>
</div>
);
}
});
React.render(
<App />,
document.getElementById('app-container')
);
% npm i markdown
var React = require('react');
var mdparser = require('markdown').markdown;
var App = React.createClass({
getInitialState: function() {
return { markdown: "" };
},
updateMarkdown: function(markdown) {
this.setState({ markdown: markdown });
},
render: function() {
return (
<div>
<TextInput onChange={ this.updateMarkdown } />
<Markdown markdown={ this.state.markdown } />
</div>
);
}
});
var TextInput = React.createClass({
propTypes: {
onChange: React.PropTypes.func.isRequired
},
_onChange: function(e) {
this.props.onChange(e.target.value);
},
render: function() {
return (
<textarea onChange={ this._onChange }></textarea>
);
}
});
var Markdown = React.createClass({
propTypes: {
markdown: React.PropTypes.string.isRequired
},
render: function() {
var html = mdparser.toHTML(this.props.markdown);
return (
<div dangerouslySetInnerHTML={{ __html:html }}></div>
);
}
});
React.render(
<App />,
document.getElementById('app-container')
);
- PropTypes
- Props で渡ってくる値の型をチェックしバリデーションを行うための機構
- HTML 文字列を DOM として追加する
- dangerouslySetInnerHTML 属性を用いて DOM 追加
- 落ち葉拾い
- DOM 操作のために jQuery はもう必要無い
- Virtual DOM を前提にする以上、生 DOM を直接操作する jQuery を併用できないと考えたほうがよい
- Flux