昨日は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間のやりとりについて書きたいと思います。