今更ながらReactJSを勉強をしたメモです。
ReactJSとは
Reactを動かしてみる
公式サイトに書いてある通りにStarter Kit
をインストールしてサンプルを動かしてみました。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> <script src="./react.js"></script> <script src="./JSXTransformer.js"></script> </head> <body> <div id="example"></div> <script type="text/jsx"> React.render( <h1>Hello, world!</h1>, document.getElementById('example') ); </script> </body> </html>
ブラウザで実行されてくれました。
JSのコード中にhtmlタグ入ってるのですが、これはJSX
というものがうまくJSのコードになおしてくれているようです。
Reactのチュートリアルをやってみる
createClassを使う
続けて公式サイトのチュートリアルを見ながらタスクリスト作成に挑戦してみました。
先ほどのhtmlにJquery
の読み込みを追加してJS部分を下のように書き換えます。
// tutorial1.js var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> Hello, world! I am a CommentBox. </div> ); } }); React.render( <CommentBox />, document.getElementById('content') );
下のような表示になりました。
React.createClass
を使うと独自のタグを作れるみたいです。
JSXがない場合
JSXを使わない場合は下のような書き方になるようです。
JSX使う方がはるかに見やすいですね。
<script type="text/javascript"> var CommentBox = React.createClass({ render: function() { return ( React.createElement('div', {className: "commentBox"}, "Hello, world! I am a CommentBox.") ); } }); React.render( React.createElement(CommentBox, null), document.getElementById('content') ); </script>
クラスの入れ子
下のように要素の入れ子もできるようです。
var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> <CommentBoxChild1 /> <CommentBoxChild2 /> </div> ); } }); var CommentBoxChild1 = React.createClass({ render: function() { return ( <div className="commentBoxChild1"> Child1 </div> ); } }); var CommentBoxChild2 = React.createClass({ render: function() { return ( <div className="commentBoxChild2"> Child2 </div> ); } }); React.render( <CommentBox />, document.getElementById('content') );
下のように2つの要素が表示されました。
renderの中身
render
の中身はタグをなくせるのか気になったので調べてみました。
確認した所タグをなくすのはできませんでした。
あとタグはdiv以外でも大丈夫なようです。
// これは動かない render: function() { return ( Hello world ); } // これも動かない render: function() { return ( <span> Hello </span>World ); } // これは動く render: function() { return ( <span> Hello world </span> ); }
変数を使う
変数を使いたい場合は{}
で囲めば良さそうです。
var value = 1; var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> {value} </div> ); } }); React.render( <CommentBox />, document.getElementById('content') );
他要素へ値を渡す
他の要素へ変数を渡す場合は下のようにします。
渡す方はタグの要素として設定します。
受け取る側はthis.props
で受け取れるようです。
var CommentBox = React.createClass({ render: function() { return ( <div>{this.props.text}</div> ); } }); React.render( <CommentBox text={a: 1} />, document.getElementById('content') );
下のように文字列以外を渡す事もできました。
var CommentBox = React.createClass({ render: function() { return ( <div>{this.props.text.a}</div> ); } }); var value = {a: "Hello"} React.render( <CommentBox text={{a: 1}} />, document.getElementById('content') );
リスト表示をする
リストは下のようにmap
を使ったら実現できました。
var CommentList = React.createClass({ render: function() { var commentNodes = ["AAA", "BBB"].map(function (component) { return ( <div> {component} </div> ); }); return ( <div className="commentList"> {commentNodes} </div> ); } }); var CommentBox = React.createClass({ render: function() { return ( <div className="commentBox"> <h1>Tasks</h1> <CommentList /> </div> ); } }); React.render( <CommentBox />, document.getElementById('content') );
データとビューのバインディング
データとビューの紐付けは下のようにstate
を使う事でできました。
紐付をすればdata
が更新された時にビューも自動で更新されます。
試しにsetTimeout
で1秒後にデータの更新をしてみました。
var CommentList = React.createClass({ render: function() { var commentNodes = this.props.data.map(function (component) { return ( <div> {component} </div> ); }); return ( <div className="commentList"> {commentNodes} </div> ); } }); var CommentBox = React.createClass({ getInitialState: function() { return {data: []}; }, componentDidMount: function() { self = this; setTimeout(function() { self.setState({data: [{name: "SSS"}]}) }, 1000); }, render: function() { return ( <div className="commentBox"> <h1>Tasks</h1> <CommentList data={this.state.data} /> </div> ); } }); React.render( <CommentBox />, document.getElementById('content') );
ワンテンポ置いてから下のような表示に切り替わりました。
タスクの追加をしてみる
今までやった事を参考にタスクの追加処理を実装してみます。
フォームで保存ボタンを押した時にsetState
で新しい値を保存するようにしました。
var TaskForm = React.createClass({ handleSubmit: function(e) { e.preventDefault(); this.props.onSubmit(this.refs); }, render: function() { return ( <form className="commentForm" onSubmit={this.handleSubmit}> <input type="text" placeholder="name" ref="name" /> <input type="submit" value="保存" /> </form> ); } }); var TaskList = React.createClass({ render: function() { var taskNodes = this.props.tasks.map(function (task) { return ( <div> {task} </div> ); }); return ( <div className="taskList"> {taskNodes} </div> ); } }); var TaskBox = React.createClass({ getInitialState: function() { return {tasks: []}; }, onSubmit: function(form) { this.setState({tasks: this.state.tasks.concat(React.findDOMNode(form.name).value)}); }, render: function() { return ( <div className="taskBox"> <h1>Tasks</h1> <TaskList tasks={this.state.tasks} /> <TaskForm onSubmit={this.onSubmit} /> </div> ); } }); React.render( <TaskBox />, document.getElementById('content') );
下のように追加できるようになりました。
まとめ
きれいな書き方とかは全然分かってないのですが とりあえずタスクを追加する所までできました。
編集・削除も時間あればやってみようと思います。