React における setState の同期または非同期の問題の理解

React における setState の同期または非同期の問題の理解

1. setState は同期的ですか?非同期ですか?

React のクラス コンポーネントでは、setState メソッドを使用して状態を更新できます。しかし、setState を使用した後、最新のデータを取得できない場合があります。

実際、React における setState の実行プロセス自体はコードと同期されており、これは React フレームワーク自体のパフォーマンス最適化メカニズムによってのみ発生します。 React では、更新前に合成イベントとライフサイクル関数が呼び出されるため、合成イベントとライフサイクル関数で更新された値をすぐに取得できず、非同期形式になります。

合成イベントで setState メソッドが n 回呼び出された場合、React が最適化されていないと、現在のコンポーネントが n 回レンダリングされ、パフォーマンスが大幅に無駄になります。したがって、パフォーマンス上の理由から、React は setState メソッドへの複数の呼び出しを 1 回の実行にマージします。 setState を実行しても、状態内のデータはすぐには更新されません。

前述したように、React の合成イベントとライフサイクル関数で setState を直接呼び出すと、非同期的に動作します。

さらに、React のパフォーマンス最適化メカニズムをバイパスし、ネイティブ イベントで setState または setTimeout を使用すると、同期的に動作します。

2. 非同期的に動作する

1. React合成イベント

onChange、onClick など、React で直接使用されるイベントは、React によってカプセル化されたイベントです。これらは合成イベントであり、React によって管理されます。すると、パフォーマンス最適化メカニズムにより、合成イベントで setState を直接呼び出すと非同期になります。

次のコードでは、合成イベント onClick で、状態内の count が直接 1 増加し、その後 count の値が出力されます。その結果、ボタンが初めてクリックされたときに、最新の 1 ではなく 0 が出力されます。

状態 = { カウント: 0 };
追加 = () => {
    this.setState({ count: this.state.count + 1 });
    console.log(this.state.count); // 0
};
与える() {
    戻る (
        <>
            <div>現在のカウント: {this.state.count}</div>
            <button onClick={this.add}>追加</button>
        </>
    );
}

2. ライフサイクル機能

ライフサイクル関数も React によって管理されます。ライフサイクル関数内で setState を直接呼び出すと、非同期的に動作します。

次のコードでは、ライフサイクルのcomponentDidMount関数で、状態内のカウントが1増加し、その後countの値が出力されます。結果は最新の1ではなく0になります。

状態 = { カウント: 0 };
コンポーネントマウント() {
    this.setState({ count: this.state.count + 1 });
    console.log(this.state.count); // 0
}
与える() {
    戻る (
        <>
            <div>現在のカウント: {this.state.count}</div>
            <button>追加</button>
        </>
    );
}

3. 同期として表示される

1. ネイティブイベント

setState の実行プロセス自体は同期的です。ネイティブ イベントを使用し、React の管理をバイパスすると、同期フォームが表示されます。

次のコードは、ID によって DOM 要素を取得し、ネイティブ メソッドを使用してクリック イベントをバインドします。クリックイベントでは、状態の count に 1 を追加し、count の値を出力します。その結果、最新の count 値 1 が出力されます。

状態 = { カウント: 0 };
コンポーネントマウント() {
    btn = document.getElementById('btn');
    btn.onclick = () => {
        this.setState({ count: this.state.count + 1 });
        console.log(this.state.count); // 1
    };
}
与える() {
    戻る (
        <>
            <div>現在のカウント: {this.state.count}</div>
            <button id="btn">追加</button>
        </>
    );
}

2.タイムアウトを設定する

次のコードは、ライフサイクルのcomponentDidMount関数にタイマーsetTimeoutを記述します。setTimeout内では、状態のcountが1増加し、その後countの値が出力されます。その結果、最新のcount値1が出力されます。

setState はライフサイクルの componentDidMount 関数にも記述されていますが、componentDidMount に直接記述されているわけではなく、setTimeout のレイヤーでラップされています。このように、setState は同期的に動作します。

状態 = { カウント: 0 };
コンポーネントマウント() {
    タイムアウトを設定する(() => {
        this.setState({ count: this.state.count + 1 });
        console.log(this.state.count); // 1
    }, 0);
}
与える() {
    戻る (
        <>
            <div>現在のカウント: {this.state.count}</div>
            <button>追加</button>
        </>
    );
}

4. setStateの2番目のパラメータ

setState がオブジェクト指向形式で記述されているか関数指向形式で記述されているかに関係なく、オプションのコールバック関数である 2 番目のパラメーターがあります。このコールバック関数は、状態が更新され、インターフェイスが更新された後 (render が呼び出された後) にのみ呼び出されます。

以下のコードのように、componentDidMount 内で直接 setState を呼び出していますが、setState のコールバック関数内で count の値が出力され、最新の値 1 が取得されています。状態が更新された後にコールバック関数が呼び出されるので、当然最新の count が取得できます。

状態 = { カウント: 0 };
コンポーネントマウント() {
    this.setState({ count: this.state.count + 1 }, () => {
        console.log(this.state.count); // 1
    });
}
与える() {
    戻る (
        <>
            <div>現在のカウント: {this.state.count}</div>
            <button>追加</button>
        </>
    );
}

React の setState の同期または非同期の問題を理解するこの記事はこれで終わりです。React の setState の同期または非同期に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • React における同期および非同期 setState の問題のコード分析
  • ReactでのsetStateの使用と同期と非同期の使用
  • React での setState 同期および非同期シナリオの使用

<<:  HTMLテキストの一般的なイベントとメソッドの詳細な説明

>>:  MySQLの3値ロジックとNULLの詳細な説明

推薦する

JavaScript で文字列を数値に変換する方法

目次1.parseInt(文字列、基数) 2. 数値() 3.parseFloat()主なメソッドは...

マーキー要素は、スクロールするフォントや画像などの効果を実装します。

マーキー要素を使用すると、単純なフォント(画像など)のスライドやその他の効果を実現できます。コードを...

VMware Workstation での VMware vSphere のセットアップ (グラフィック チュートリアル)

VMware vSphere は、業界をリードする最も信頼性の高い仮想化プラットフォームです。 v...

Vueはスクロールバースタイルを実装します

最初はブラウザのスクロールバーのスタイルを変更して効果を実現したいと思っていましたが、情報を調べてみ...

HTML ではスペースはどのように表現されますか (どのような意味ですか)?

Web 開発では、次のような文字によく遭遇します: &nbsp;これは実際には HTML が...

Docker での Tomcat インストールの 404 問題の解決方法

tomcat の containerID を見つけて、tomacat ディレクトリに入ります。 [r...

Vue プロジェクトでブラウザ キャッシュ設定を無効にする例

プロジェクトをリリースするときに、キャッシュをクリーンアップする必要があるという問題に遭遇することが...

Vueはショッピングカート決済機能をシミュレートします

この記事では、ショッピングカート決済機能を実現するためのVueの具体的なコードを例として紹介します。...

Linuxで中断されたシステムを呼び出す方法

序文低速システム コールとは、決して戻らない可能性があり、プロセスを永久にブロックするシステム コー...

初心者がHTMLタグを学ぶ(1)

初心者は、いくつかの HTML タグを理解することで HTML を学習できます。この入門書は、初心者...

Reactの原理の説明

目次1. setState() の説明1.1 データの更新1.2 推奨構文1.3 2番目のパラメータ...

純粋な JS を使用して vue.js で双方向バインディング機能を実装する方法

目次まず、双方向バインディングを実装するアイデアについて説明します。これらの機能を実装するための j...

Mysql論理アーキテクチャの詳細な説明

1. 全体的なアーキテクチャ図他のデータベースと比較すると、MySQL は、そのアーキテクチャがさま...

Dockerコンテナの構築と実行のプロセスの詳細な説明

イメージをプルし、コンテナを作成してコンテナを実行するだけです。 docker run -d --r...

HTML シンボルからエンティティへのアルゴリズムのチャレンジ

チャレンジ:文字列内の文字 &、<、>、" (二重引用符)、および &...