React?に非同期getState関数がない理由
ドキュメントから、setStateは非同期であることがわかります。ただし、これはthis.stateを安全に使用できないことを意味し、実行順序を尊重するために非同期getStateも必要です。
私が理解していることから、this.stateを使用して、次のようなgetState関数を使用しないでください
getState(callback) {
this.setState((prevState) => {
callback(prevState) ;
});
}
...
this.getState((curState) => {
// we now can use the current state safely
}
私の考え方でここに欠けているものはありますか?なぜそのような関数がReact?
-編集-
私の友人が私に言ったように、それは明確ではなく、私は確信していないが最初の答えなので、いくつかのコードを分析しましょう:
simpleFunc() {
setState({ "counter" : 1 });
setState({ "counter" : 2 });
this.state.counter // => no garanty about the value
getState((curState) => { // ensure curState.counter is 2 });
}
この簡単な例は、setStateが非同期であるため、すべての状況でthis.stateを直接使用できないことを示しています。
GetStateを使用できるカウンターの例を次に示します。 http://codepen.io/Epithor/pen/ZLavWR?editors=0010#
簡単な答え:悪い状態です。
回避策は簡単ですが、一部の関数を因数分解し、コンテキストを気にせずに使用できるという事実は興味深いようです。
したがって、特定の順序で多数のイベントが発生すると、一部のイベントは状態を変更し、一部のイベントは状態を読み取ります:イベントがthis.stateすべての変更が非同期であるため、良好な状態を読み取るには?
実際にはすべては時間についてです:
T : event 1, change state
T+1ms : event 2, change state
T+2ms : event 3, read state
T+3ms : event 4, change state
イベント1または2のsetStateが正確にいつ発生するかを予測できないため、イベント3がイベント2で設定された状態を実際に読み取ることをどのように保証できますか?
短い答え:イベントはJSスタックでキューに入れられますが、状態変更は内部でキューに入れられますReactキュー。内部Reactキューはハンドを与える前に完全にアンスタックされます。
間違いなく_this.state
_を直接一般的に使用できます。状態を直接mutateしてはいけません(_this.state.foo = 0
_)、代わりにsetState
を使用して状態を変更する必要があります。
通常、setState
は次のようになります。
_this.setState({
foo: 0
})
_
その後、render()
関数などで_this.state.foo
_を安全に使用できます。
ただし、setState
の非同期的な性質により、setState
が呼び出された後に_this.state
_にすぐにアクセスできるという保証はありません。
_myFunc(baz) {
this.setState({
foo: baz + 1
})
console.log(this.state.foo) // not guaranteed
}
_
やったほうがいい
_myFunc(baz) {
const bazOne = baz + 1
this.setState({
foo: bazOne
})
console.log(bazOne)
}
_
または、setState
関数の2番目のパラメーターを使用します。これは、setState操作が終了したときに実行されるコールバックとして使用されます。そのコールバックでは、更新された状態、つまり_this.state
_にアクセスできます。
this.setState({ foo }, () => { console.log(this.state.foo) });
参照: https://facebook.github.io/react/docs/react-component.html#setstate
それは実際にはバグ/問題ではなく、アーキテクチャの決定です:state
は単純なプロパティ/変数/ストレージとして使用されることを意図していません。 、呼び出しごとに更新する必要はありません。内部キューを使用するため、レンダリングの前に何度も状態をスワップすると、実際には最終値で1回だけ更新され、render
メソッドが呼び出されるまでに適切な値が含まれます。
実行中または同じフェーズで実行されるメソッド間(たとえば[componentWillReceiveProps
とshouldComponentUpdate
)で情報を保存/取得する必要がある場合は、this.anyProperty
を安全に使用できます。常に:
componentWillReceiveProps() {
this.value = 'guaranteed';
return true;
}
shouldComponentUpdate() {
if (this.value === 'guaranteed') {
console.log('will always return true');
}
}
componentDidUpdate() {
this.value = ''; //cleanup
}
上記の例では、「setState」を使用した場合、「shouldComponentUpdate」で値が常に更新されるという保証はありませんが、意図した目的で使用するかどうかは重要ではありません。状態の変更はrender
時間までにフラッシュされることが保証されているため、オブジェクトのトランザクション/内部データではなく、レンダリングフェーズで使用される情報のみが含まれている必要があります。通常どおり、オブジェクトのプロパティを自由に使用できます。
setStateは非同期であるため、変更したプロパティにすぐにアクセスすることはできませんが、状態が変更された後にアクションを実行したい場合があります。
...
this.state = {
x = 1
}
...
this.setState({
x = 2
}, () => {
console.log(this.state.x) // outputs 2
});
setState関数はキューに入れられたティックで呼び出されるので、x個のsetStateをキューに入れることができ、それらはすべて次のティックで実行されます。