web-dev-qa-db-ja.com

React setStateコールバックを使用する場合

反応コンポーネントの状態が変化すると、renderメソッドが呼び出されます。したがって、どのような状態変化に対しても、renderメソッド本体でアクションを実行できます。それならsetStateコールバックのための特定のユースケースはありますか?

129
Sahil Jain

setStateasynchronousのように機能するので、あります。 setStateを呼び出した後、this.state変数はすぐには変更されません。そのため、状態変数に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()ではなくコールバックでそれを実行したいと思うでしょう。なぜならそれは再レンダリングが起こるたびに呼ばれるでしょうから、コールバックを必要とするところではそのようなシナリオの多くが可能です。

もう1つのケースはAPI Callです

特定の状態の変化に基づいてAPI呼び出しを行う必要がある場合があります。renderメソッドでそれを行うと、すべてのrenderのonStateの変更時、またはChild Componentに渡されたPropが変更されるたびに呼び出されます。

この場合は、更新された状態値をAPI呼び出しに渡すためにsetState callbackを使用します。

....
changeTitle: function (event) {
  this.setState({ title: event.target.value }, () => this.APICallFunction());
},
APICallFunction: function () {
  // Call API with the updated value
}
....
173
Shubham Khatri

私の頭に浮かぶ1.ユースケースはapi呼び出しです。これはeach状態の変更のために実行されるので、これはレンダリングに入るべきではありません。そして、API呼び出しは、 every renderではなく、特別な状態の変化に対してのみ実行されるべきです。

changeSearchParams = (params) => {
  this.setState({ params }, this.performSearch)
} 

performSearch = () => {
  API.search(this.state.params, (result) => {
    this.setState({ result })
  });
}

したがって、どのような状態変化に対しても、renderメソッド本体でアクションを実行できます。

非常に悪い習慣 render-メソッドは純粋でなければならないので、アクション、状態の変更、API呼び出しは実行しないでください。ビューを合成して返すだけです。アクションは一部のイベントに対してのみ実行する必要があります。 Renderはイベントではなく、たとえばcomponentDidMountです。

38
webdeb
this.setState({
    name:'value' 
},() => {
    console.log(this.state.name);
});
22
Araz Babayev

SetState呼び出しを検討する

this.setState({ counter: this.state.counter + 1 })

IDEA 1

setStateは非同期関数で呼び出すことができます

したがって、thisに依存することはできません。上記の呼び出しが非同期関数の内部で行われた場合、thisはその時点でのコンポーネントの状態を参照しますが、これはsetState呼び出し時または非同期タスクの開始時の状態内部のプロパティを参照することが期待されます。タスクは非同期呼び出しであったため、そのプロパティは当分変更された可能性があります。したがって、thisキーワードを使用して状態のプロパティを参照することは信頼できません。したがって、引数がpreviousStateとpropsであるコールバック関数を使用します。つまり、非同期タスクが実行され、 setStateがまだ開始されていない場合に、今すぐ状態になります。 nextStateが破損しないという信頼性を確保します。

間違ったコード:データの破損につながる

this.setState(
   {counter:this.state.counter+1}
 );

コールバック機能を持つsetStateの正しいコード:

 this.setState(
       (prevState,props)=>{
           return {counter:prevState.counter+1};
        }
    );

したがって、現在のプロパティが現在所有している値に基づいて現在の状態を次の状態に更新する必要があり、これがすべて非同期で発生する場合は、setStateをコールバック関数として使用することをお勧めします。

IDEA 2

SetState呼び出しはasyncである可能性がありますbczReactは、パフォーマンスのために2つ以上のsetState呼び出しを組み合わせようとする場合があります改善。 とにかく信頼できない。 2つのsetState呼び出しがt = 0で発生するとします。どちらも、呼び出し前に同じ状態(state_0)を参照していたため、どちらが先に終了するかは非同期です。 1つの呼び出しがstate_1になり、そのうちの1つが終了するとします。状態が初期状態を参照していた他の呼び出し(state_0)は、state_3。そして、これは州とそのデータの破損につながる可能性があります。コールバック関数への引数がprevStateであるコールバックを使用する、小道具。それらのいずれかが最初に終了してstate_1になる場合、次のsetStateは常にprevStateを初期状態として参照します。したがって、データが破損しないことを常に確認してください。 setStateが同時に呼び出されるため、この方法でデータが破損することはほとんどありません。ただし、次の状態がprevStateに依存する必要がある場合は、常にコールバックを使用します。

ここでコードペンで説明しようとしましたCODE PEN

21
Aniket Jha