React.jsの実践といえばやはりAjaxを扱う環境でしょう!
ということで前回の基礎編に続いて、Ajaxで非同期通信したデータをもとにコンポーネントを生成していきます。
Ajax通信をしてコンポーネントを生成する
これまでは、propsとして値を一度だけレンダリングしていましたが、これは親から渡されるものなので子から変更することができません。
そこで、stateを使って子にプライベートな値を持たせ、setState()で自由に値を更新していきます。
list.jsonを読み込んで、コンポーネントを表示させたいと思います。
list.json
[
{'id':0, 'str': 'list01'},
{'id':1, 'str': 'list02'},
{'id':2, 'str': 'list03'},
];
render.js
var Compornent = React.createClass({
getInitialState: function(){
return { data: [] };
},
loadCommentsFromServer: function(){
$.ajax({
url: this.props.url,
dataType: 'json',
cache: 'false',
success: function(data){
this.setState({ data: data });
}.bind(this),
error: function(xhr, status, err){
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
componentDidMount: function(){
this.loadCommentsFromServer();
},
render: function(){
return (
<ul>
{this.state.data.map(function(result){
return (
<li key={result.id}>
{result.str}
</li>
);
})}
</ul>
);
}
});
ReactDOM.render(
<Compornent url="/list.json" />,
document.getElementById('content')
);
React.createClass()のgetInitialStateで値を初期化します。
loadCommentsFromServerでajax通信用関数を定義し、componentDidMountで実行します。
そして、this.state.data.map()で展開しています。
このコンポーネントの生成では、レンダリングは一度しか行われませんが、setState()で何度でも値を更新することができます。
実際に、イベントを使って試してみましょう。
コンポーネントにイベントを追加する
リストタグの他にボタンを生成し、それにonClickイベントを追加します。
React.createClass()内で、onClickイベントを作ります。
render.js
var Compornent = React.createClass({
getInitialState: function(){
return { data: [] };
},
loadCommentsFromServer: function(){
$.ajax({
url: this.props.url,
dataType: 'json',
cache: 'false',
success: function(data){
this.setState({ data: data });
}.bind(this),
error: function(xhr, status, err){
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
componentDidMount: function(){
this.loadCommentsFromServer();
},
onClick: function(){
var number = this.state.data.length + 1;
var str = {'id':(number - 1), 'str': 'list0'+ number};
this.state.data.push(str);
this.setState({ data: this.state.data });
},
render: function(){
var _this = this;
return (
<div>
<ul>
{this.state.data.map(function(result){
return (
<li key={result.id}>
{result.str}
</li>
);
})}
</ul>
<button onClick={_this.onClick}>CLICK</button>
</div>
);
}
});
ReactDOM.render(
<Compornent url="./list.json" />,
document.getElementById('content')
);
onClickで、クリックすると配列を追加するという命令をしています。
そして、this.setState({ data: this.state.data })で、データを更新しています。
すると、自動でレンダリングされリストタグがどんどん増えていきます。
コンポーネントにイベントを追加する(応用編)
今度は、リストタグをクリックすると、下の要素内にクリックしたリストタグの内容を表示したいと思います。
render.js
var Compornent = React.createClass({
getInitialState: function(){
return { data: [], commment: null };
},
loadCommentsFromServer: function(){
$.ajax({
url: this.props.url,
dataType: 'json',
cache: 'false',
success: function(data){
this.setState({ data: data });
}.bind(this),
error: function(xhr, status, err){
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
componentDidMount: function(){
this.loadCommentsFromServer();
},
onClick: function(key){
var $elem = $(key.target);
var str = $elem.text();
this.setState({ commment: str });
},
render: function(){
var _this = this;
return (
<div>
<ul>
{this.state.data.map(function(result){
return (
<li onClick={_this.onClick} key={result.id}>
{result.str}
</li>
);
})}
</ul>
<div id="comment">{this.state.commment}</div>
</div>
);
}
});
ReactDOM.render(
<Compornent url="./list.json" />,
document.getElementById('content')
);
getInitialStateで、初期配列を新しくセットします。
今度は、リストタグにonClickを追加しました。
ここで、onClickに引数でkeyを持ってくると、$(key.target)でクリックした要素をjQueryで扱うことができます。
これですっごくコードが少なくなるので、jQueryを普段からお使いの方はおすすめですよv
そうすると、idがcommentのdivの中に、クリックしたリストタグの文字列が入ります。
最後に
慣れるまではちょっと小難しく感じてしまいますが、決め打ちの部分も多く、概念は理解しようと思えば思うほどきりがなかったです;(
前回お話した概念を頭の隅におきつつ、動作を検証していくと新しい発見もあるかもしれません。
今までのAjaxからDOM操作してた時と比べると軽すぎ!ってくらい動作サクサクです◎
Ajaxで読み込んだデータでDOM生成しても、管理も楽だし動作も軽くて、React.jsなかなかお気に入りです!