昨日はPropについて紹介しましたが、StateはPropがImmutableな値であったのに対してMutableな値を定義することが出来ます。
基本的な使い方
基本的にはgetIntialStateでstateの初期値を返して、データに変更があった場合にthis.setStateで更新します。
そうするとComponentがrerenderされて表示が更新されます。子のComponentもrerenderされます。
var Counter = React.createClass({
getInitialState() {
return {
count: 0
};
},
onClick() {
this.setState({ count: this.state.count + 1});
},
render() {
return (
<div>
<span>{this.state.count}</span>
<button onClick={this.onClick}>click</button>
</div>
);
}
});
setStateの第二引数にはsetPropsと同様にcallback関数を指定することが出来ます。
また、setPropsに対してのreplacePropsのようにreplaceStateというstateを置き換える関数もあります。
Stateを使う場面
一番よく使うのがtext fieldのようなComponent内でユーザーのアクションによって変化する値を管理するような場合です。
また、そのComponentが必要とするデータをComponent内でAjaxで取得し反映する場合なども、Ajaxのcallback関数内でresponseをsetStateするように使います。
注意点
stateの値は直接更新してはダメで必ずsetState経由で更新する必要があります。
これはsetStateが呼ばれることでrerenderされるためで、this.stateの値自体もImmutableであると考えておくのがいいとされています。
なので、this.state.listな値があってlistに要素を追加したい時も、pushしてsetStateするのではなくてthis.setState({ list: this.state.list.concat([val]) })として新しい値(配列)にしておいた方がshouldComponentUpdateでチューニングする際にも都合がいいですし、undoの実装なんかもやりやすくなります。
Stateは最低限に
Propだけを持っているようなImmutableなComponentの方が扱いやすいしわかりやすいので、基本的にはPropで考えてStateを持つComponentは最低限にしておくのがよいです。
React.jsでは、rootとなるComponentだけにStateを持たせて後は全部Propだけを持ってるImmutableなComponentにして、何か変更があるとrootのComponentでsetStateしてまとめてrerenderするような構成も可能だったりします。その辺りはVirtualDOMのなせる技なのですが、それはまた別の日に...。
明日はPropやStateを使ってのComponent間のやりとりについて書きたいと思います。