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の詳細な説明

推薦する

CSS のグリッドプロパティの使用に関する詳細な説明

グリッドレイアウト親要素に追加された属性グリッドテンプレートの列/グリッドテンプレートの行要素の行ま...

CSS3 カウントダウン効果

成果を達成する実装コードhtml <div クラス = 'ラッパー'> ...

HTML テーブルタグチュートリアル (19): 行タグ

<TR> タグの属性は、次の表に示すように、テーブル内の各行のプロパティを設定するために...

「いいね!」文がインデックスに登録されないのはなぜですか?

序文この記事は、最も人気のある言語で最も退屈な基礎知識を説明することを目的としていますこのトピックは...

MySQLデータベース入門:データベースバックアップ操作の詳細な説明

目次1. 単一データベースのバックアップ2. 圧縮バックアップ3. マルチデータベースバックアップ4...

CSS を使用して複数の方法で等幅レイアウトを実装するサンプルコード

この記事で説明する等幅レイアウトでは、純粋な CSS を使用して、要素の幅を手動で設定することなく、...

VScode設定のリモートデバッグLinuxプログラムの問題を解決する

VScode リモートデバッグ Linux プログラムの問題について見てみましょう。具体的な内容は以...

Linux ファイアウォール設定の詳細な手順 (yum ウェアハウス設定に基づく)

序文この実験では、デバッグ用に2つの仮想マシン(CentOs6とRed Hat 6)を準備します。 ...

Redux Toolkit で Redux を簡素化する方法

目次Redux Toolkitが解決する問題何が含まれていますか? Redux Toolkit AP...

Navicat を仮想マシン MySQL に接続する際によくあるエラーと解決策

質問1 解決するサービスを開始します: service mysqld start; /sbin/ip...

Docker イメージのダウンロードが遅すぎる場合の解決策

Docker イメージのダウンロードが停止したり、遅すぎたりするネットでいろいろな方法を検索しました...

Tomcat が https アクセスをサポートするための手順の説明

tomcat を https アクセスに対応させる方法ステップ: (1)キーストアファイルを生成する...

イメージのパッケージ化とワンクリック展開を実現するためにDockerを組み合わせたアイデア

1. サーバーにDockerをインストールする yumでdockerをインストール設定ファイルを変更...

MySQL インポートおよびエクスポートのバックアップの詳細

目次1. MySQLのバックアップタイプの詳細な説明1. バックアップがデータベースに与える影響に基...