setStateの概要
setStateは、Reactが状態を管理するための重要なメソッドです。
setState公式の使い方
- 構文1: setState(updater[, callback])
- updater: 関数型で、更新された状態のstateオブジェクトを返します。
- callback: オプション、コールバック関数。
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
- 構文 2: setState(stateChange[, callback])
- stateChange: オブジェクト型で、入力されたオブジェクトを新しい状態に浅くマージします。
- callback: オプション。
// 公式には、この方法は推奨されていない。.props および this.state 非同期で更新される可能性があるので、以下で詳しく説明するように、次の状態を更新するためにその値を当てにしてはいけない。
this.setState({
counter: this.state.counter + this.props.increment,
});
setStateの第2パラメータについて:
2番目のパラメータは、setState関数が呼び出され、コンポーネントが再レンダリングを開始したときに呼び出されるコールバック関数です。
setState を使用する際のいくつかのポイント
なぜreactは this.stateで変更しないのですか?
// 状態を更新する
this.setState({count: count + 1})
//
this.state.count = count + 1
なぜなら、ステートは単なるオブジェクトであり、オブジェクトの値を変更するだけでは意味がないからです。考えてみてください。Reactコンポーネントを再描画させることなく、this.stateの値を変更するだけなら、何の意味があるでしょうか?
この時点で、状態の更新とコンポーネントの更新処理の両方を実行できる関数が必要で、その関数がsetStateです。
setStateは this.stateの値を直ちに変更するものではありません。
function incrementMultiple() {
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
}
incrementMultipleが呼び出されると、コンポーネントの状態のカウント値が3回インクリメントされ、setStateを呼び出すたびにカウント値が1回インクリメントされるはずですが、実際にはカウント値は1回しかインクリメントされません。なぜなら、this.setStateの呼び出しは this.stateをすぐに変更しないので、this.setStateは同じ値を何度も設定しているだけだからです。なぜなら、this.setStateの呼び出しは this.stateをすぐには変更しないので、this.setStateは同じ値を何度も設定しているだけだからです。
setStatethisを変更するタイミング.state
setStateは、コンポーネントの更新処理をトリガーして再描画をトリガーします setStateは、結果としてReactの更新ライフサイクル関数を呼び出します 4つの関数
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
あるいは、shouldComponentUpdateがfalseを返すと、更新処理は中断され、render関数は呼び出されません。しかし、Reactは this.stateの更新をあきらめないので、renderを呼び出さなくても this.stateは更新されます。
複数の setState 関数呼び出しによって生成された効果はマージされます。
あなたの州が複数の個別の変数を含む場合
constructor(props) {
super(props);
this.state = {
posts: [],
comments: []
};
}
setState を個別に呼び出すことで、それぞれの状態を個別に更新できます。
componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});
fetchComments().then(response => {
this.setState({
comments: response.comments
});
});
}
this".setStateは2回連続で呼び出されますが、更新のライフサイクルをトリガーするのは1回だけで、2回ではありません。なぜなら、Reactは複数の this.setStateによって生成された変更をキューに入れ、それらを保存し、準備ができたと感じたときに更新をトリガーするからです。this".setStateのたびに更新処理をトリガーするのは無駄だからです!
setStateに関数updaterを渡すことができます。
この関数は2つの引数を取ります。1つ目は現在のステート値、2つ目は現在のプロップスで、this.stateに望ましい変化を表すオブジェクトを返すはずです。しかし、このオブジェクトの計算は少し変更され、this.stateに依存しなくなり、入力パラメータのstateに依存するようになりました。
では、上の状態のカウントを増やす例を書き直してみましょう:
function increment(state, props) {
return {count: state.count + 1};
}
見ての通り、stateのカウントにも1が追加されていますが、stateのソースは this.stateではなく、入力パラメータのstateです。
function incrementMultiple() {
this.setState(increment);
this.setState(increment);
this.setState(increment);
}
関数setStateを複数回呼び出す場合、Reactは、インクリメントが呼び出されるたびに、ステートがステートの修正結果をマージしたことを確認します。
簡単に言えば、現在の this.state.countの値が0であることを追加すると、最初の呼び出し this.setState(increment)は、インクリメントに渡された状態パラメータは0であり、2回目の呼び出しの状態パラメータは1であり、3回目の呼び出しは2であり、incrementMultipleの最終的な効果は、本当に this.stateパラメータが2であることです。が0である場合、2回目の呼び出しは、状態のパラメータは1であり、3回目の呼び出しは、パラメータは2であり、incrementMultipleの最終的な効果は、本当に this.state.countを3にすることです。
this".stateは、increment関数が呼び出された時点では変更されず、render関数が再実行されるまで変更されないことは特筆に値します。
setStateの非同期と同期の問題
つまり、setStateを呼び出した後、Reactコンポーネントを再レンダリングする必要があり、レンダリング後に this.stateの状態が変更されます。しかし、setStateは同期的にコンポーネントを更新するのでしょうか。つまり、setState関数が戻ったときには、this.stateはすでに状態の変更を反映しているのでしょうか。この答えはイエスです。
Reactでは、イベントがReactによって発生した場合、setStateの呼び出しは this.stateを同期的に更新しません。そうでない場合、setStateの呼び出しは this.stateを同期的に実行します。の状態を更新します。
in addition to」とはどういう意味ですか?ReactのaddEventListenerや、setTimeout/setIntervalで生成される非同期コールをバイパスするイベントハンドラを意味します。
Reactを規律正しく使えば、"other than "を扱う必要はありません。開発のほとんどは、onChange、onClick、onTouchMoveなど、Reactによってカプセル化されたイベントを使用し、これらのイベントハンドラのsetStateは非同期で処理されます。
栗として。
constructor() {
this.state = {
count: 10
}
this.handleClickOne = this.handleClickOne.bind(this)
this.handleClickTwo = this.handleClickTwo.bind(this)
}
render() {
return (
<button onClick={this.hanldeClickOne}>clickOne</button>
<button onClick={this.hanldeClickTwo}>clickTwo</button>
<button id="btn">clickTwo</button>
)
}
handleClickOne() {
this.setState({ count: this.state.count + 1})
console.log(this.state.count)
}
出力:10
これは、ReactのラップイベントハンドラのsetStateが非同期に状態を更新することを示しています。
componentDidMount() {
document.getElementById('btn').addEventListener('clcik', () => {
this.setState({ count: this.state.count + 1})
console.log(this.state.count)
})
}
出力:11
handleClickTwo() {
setTimeout(() => {
this.setState({ count: this.state.count + 1})
console.log(this.state.count)
}, 10)
}
出力:11