反応コンポーネントの状態が変化すると、renderメソッドが呼び出されます。したがって、状態が変化した場合、レンダリングメソッドの本体でアクションを実行できます。次に、setStateコールバックの特定の使用例はありますか?
render()
代わりにこの関数を配置 すると、すべての状態が更新されるたびに実行されますが、これはおそらく望んでいないことです。これにより、コードが読みにくくなり、論理的でなくなります。
反応コンポーネントの状態が変化すると、renderメソッドが呼び出されます。したがって、状態が変化した場合、レンダリングメソッドの本体でアクションを実行できます。次に、setStateコールバックの特定の使用例はありますか?
render()
代わりにこの関数を配置 すると、すべての状態が更新されるたびに実行されますが、これはおそらく望んでいないことです。これにより、コードが読みにくくなり、論理的でなくなります。
回答:
はい以来、そこにあるsetState
で働くasynchronous
方法。つまりsetState
、this.state
変数を呼び出した後、すぐには変更されません。したがって、状態変数に状態を設定した直後にアクションを実行し、結果を返す場合は、コールバックが役立ちます
以下の例を検討してください
....
changeTitle: function changeTitle (event) {
this.setState({ title: event.target.value });
this.validateTitle();
},
validateTitle: function validateTitle () {
if (this.state.title.length === 0) {
this.setState({ titleError: "Title can't be blank" });
}
},
....
上記のコードは、title
検証が実行される前に変数が変化していない可能性があるため、期待どおりに機能しない可能性があります。これで、render()
関数自体で検証を実行できるのではないかと思うかもしれませんが、コードをより整理して理解できるようにするため、changeTitle関数自体でこれを処理できれば、より適切でクリーンな方法になります。
この場合、コールバックが役立ちます
....
changeTitle: function changeTitle (event) {
this.setState({ title: event.target.value }, function() {
this.validateTitle();
});
},
validateTitle: function validateTitle () {
if (this.state.title.length === 0) {
this.setState({ titleError: "Title can't be blank" });
}
},
....
もう1つの例はdispatch
、状態が変化したときにアクションを実行する場合です。あなたは、コールバックやないでそれを行うことになるでしょうrender()
、それは毎回再描画が発生呼び出され、コールバックを必要とする場所、したがって多くのそのようなシナリオが考えられると。
別のケースは API Call
特定の状態の変化に基づいてAPI呼び出しを行う必要がある場合、状況が発生する可能性があります。renderメソッドでそれを行うと、レンダリングがonState
変更されるたびに、または一部のプロップがChild Component
変更に渡されるために呼び出されます。
この場合、setState callback
を使用して、更新された状態値をAPI呼び出しに渡します。
....
changeTitle: function (event) {
this.setState({ title: event.target.value }, () => this.APICallFunction());
},
APICallFunction: function () {
// Call API with the updated value
}
....
if (this.title.length === 0) {
である必要がthis.state.title.length
ありますか?
setState(state => state.title.length ? { titleError: "Title can't be blank" } : null)
変更がスタックします。二重レンダリングは必要ありません。
this.setState({
name:'value'
},() => {
console.log(this.state.name);
});
1.頭に浮かぶユースケースはapi
呼び出しであり、each
状態変更のために実行されるため、レンダーには入れるべきではありません。また、API呼び出しは、すべてのレンダリングではなく、特別な状態変更時にのみ実行する必要があります。
changeSearchParams = (params) => {
this.setState({ params }, this.performSearch)
}
performSearch = () => {
API.search(this.state.params, (result) => {
this.setState({ result })
});
}
したがって、状態が変化した場合、レンダリングメソッドの本体でアクションを実行できます。
-render
メソッドは純粋でなければならないため、非常に悪い習慣です。つまり、アクション、状態変更、API呼び出しは実行されず、ビューを合成して返すだけです。アクションは、一部のイベントに対してのみ実行する必要があります。レンダリングはイベントではなく、componentDidMount
たとえばです。
setState呼び出しを検討する
this.setState({ counter: this.state.counter + 1 })
考え
setStateは非同期関数で呼び出すことができます
したがって、あなたは信頼することができませんthis
。上記の呼び出しが非同期関数内で行われた場合、this
その時点でのコンポーネントの状態を参照しますが、setState呼び出しまたは非同期タスクの開始時の状態内のプロパティを参照することを期待していました。そして、タスクは非同期呼び出しだったので、そのプロパティはしばらくすると変更された可能性があります。したがって、this
キーワードを使用して状態のプロパティを参照することは信頼できません。したがって、引数がpreviousStateとpropsであるコールバック関数を使用します。つまり、非同期タスクが実行され、setState呼び出しを使用して状態を更新するときでした。prevStateは、setStateのときに状態を参照します。まだ始まっていません。nextStateが破損しないという信頼性を保証します。
間違ったコード:データの破損につながる
this.setState(
{counter:this.state.counter+1}
);
コールバック関数を持つsetStateを含む正しいコード:
this.setState(
(prevState,props)=>{
return {counter:prevState.counter+1};
}
);
したがって、現在の状態をプロパティが持つ値に基づいて次の状態に更新する必要があり、これがすべて非同期で行われているときはいつでも、コールバック関数としてsetStateを使用することをお勧めします。