React setStateデータ更新メカニズムの詳細な説明

React setStateデータ更新メカニズムの詳細な説明

setStateを使用する理由

React 開発のプロセスでは、コンポーネントの状態を処理することが不可欠です。 React を使用したことがある人なら誰でも、状態の値を変更する場合は、内部的に提供される setState メソッドを使用する必要があることを知っています。割り当てを使用して状態の値を直接変更できないのはなぜですか?まずは分析してデモを見てみましょう。

クラス Index は React.Component を拡張します {
  この状態 = {
    カウント: 0
  }
  クリック時 = () => {
    this.setState({
       カウント: 10
    })
  }
  与える() {
    戻る (
      <div>
        <span>{this.state.count}</span>
        <button onClick={this.onClick}>クリック</button>
      </div>
    )
  }
}

上記のコードによれば、ボタンをクリックすると、state の count の値が 10 に変更されることがわかります。ページの表示を更新します。したがって、状態の変更には、対応する値の変更とページの更新という 2 つの効果があります。 **これら 2 つのポイントを実現するには、React で setState が必要です。 onClick メソッドの内容をthis.state.count = 10に変更し、メソッド内でthis.stateの値を出力すると、state の値が変更されたことがわかります。しかし、ページは最新の値に更新されません。 ☆まとめ:

  • 状態値を変更する目的は、ページを更新することです。React が最新の状態を使用してページをレンダリングすることを期待します。ただし、直接割り当て方式では、React は状態の変化を監視できません。
  • 状態データが変更したことを React に通知するには、setState メソッドを使用する必要があります。

☆拡大するには:

Vue では、データの更新に直接割り当てが使用され、Vue は最新のデータを使用してページをレンダリングすることもできます。これはなぜでしょうか? vue2 では、データの変更を監視するために、Object.defineProperty() を使用してデータの get メソッドと set メソッドを監視します。vue3 では、データの変更を監視するために ES6 プロキシが使用されます。

setStateの使用法

setState の使い方は皆さんご存知だと思いますが、ここでも記録しておきます。setState メソッドには 2 つのパラメーターがあります。最初のパラメーターは、プロパティ値を直接変更するオブジェクトにすることも、以前の状態値を取得できる関数にすることもできます。 2 番目のパラメータは、最新の状態値を取得できるオプションのコールバック関数です。コールバック関数は、コンポーネントの更新が完了した後に実行されます。これは、 componentDidUpdateライフサイクル中に実行されるのと同じです。

  • 最初のパラメータがオブジェクトの場合: 上記のデモと同様に、stateの属性値を直接変更します。
this.setState({
	キー:newState
})
  • 最初のパラメータが関数の場合: 関数内で前の状態のプロパティ値を取得できます。
// prevState は前の状態、props はこの更新が適用されたときのプロパティです
this.setState((前の状態、props) => {
  戻る {
      キー: prevState.key 
  }
})

非同期または同期更新

setState() はコンポーネントの状態の変更をキューに入れて、このコンポーネントとその子を更新された状態で再レンダリングする必要があることを React に通知します。これは、イベント ハンドラーとサーバー データに応答してユーザー インターフェイスを更新する主な方法です。setState() を、コンポーネントを更新するための即時コマンドではなく、要求として扱います。パフォーマンスをより良く認識するために、React はこれを遅延呼び出しし、1 回のパスで複数のコンポーネントを更新します。 React は状態の変更がすぐに有効になることを保証しません。

まずは上記のコードを修正してみましょう。前述のように、onClick メソッドで setState が 3 回連続して呼び出される場合、setState は非同期メソッドです。各呼び出しでは、変更がキューに追加されるだけです。同期的に呼び出すと、最後の更新のみが実行されるため、結果は 3 ではなく 1 になります。

クリック時 = () => {
  const { count } = this.state
  this.setState({ count: count + 1 })
  this.setState({ count: count + 1 })
  this.setState({ count: count + 1 })
}

上記のコードはObject.assign()メソッドとして理解できます。

オブジェクト.assign()
  州、
  { カウント: 状態.count + 1 },
  { カウント: 状態.count + 1 },
  { カウント: 状態数 + 1 }
)

関数が最初のパラメータとして渡され、3 回連続して呼び出された場合、結果はオブジェクトとして渡した場合と同じになりますか?

クリック時 = () => {
  this.setState((前の状態、props) => {
    戻る {
      カウント: prevState.count + 1
    }
  })
  this.setState((前の状態、props) => {
    戻る {
      カウント: prevState.count + 1
    }
  })
  this.setState((前の状態、props) => {
    戻る {
      カウント: prevState.count + 1
    }
  })
}

オブジェクトを渡す方法とは全く異なる結果になります。関数メソッドを使用すると、3 増加の効果が得られます。これはなぜでしょうか? 関数内で最新の状態とプロパティの値を取得できます。上記から、setState がバッチで更新されていることがわかります。関数を使用すると、現在の状態が以前の状態に基づいていることが保証されるため、3 ずつ自己増加させる効果が得られます。

☆まとめ: setState メソッドが非同期なのはなぜでしょうか?

  • パフォーマンスを大幅に向上できます。React16 では、タスクを分割して優先順位を付け、優先度の高いタスクを優先する Fiber アーキテクチャが導入されました。ページの応答は優先度の高いタスクであるため、setState が同期の場合、ページが更新されるとすぐに更新する必要があり、ページの応答がブロックされます。最善のアプローチは、複数の更新を取得してからバッチ更新を実行することです。ページを一度だけ更新します。
  • 状態が同期的に更新されても、レンダリング関数がまだ実行されていない場合、状態とプロパティを同期させることはできません。

**すべての setStates は非同期ですか? **答えはイエスです! ! ! React で setState が同期されるシナリオもあります。

クリック時 = () => {
	this.setState({ count: this.state.count + 1 })
  コンソールログ(この状態)
  タイムアウトを設定する(() => {
    this.setState({ count: this.state.count + 1 })
    コンソールログ(この状態)
  }, 0)
}

上記のコードは **0, 2 を出力します。 **これはなぜでしょうか?実際、React の setState は厳密な意味では非同期関数ではありません。これはキューの遅延実行を通じて実装されます。 isBatchingUpdatesを使用して、現在の setState が更新キューに追加されるか、ページが更新されるかを決定します。 isBatchingUpdates=tureの場合は更新キューに追加し、それ以外の場合は更新を実行します。

React はisBatchingUpdatesを使用して更新キューに参加するかどうかを決定することがわかっています。では、なぜsetTimeoutイベントでisBatchingUpdates値がfalseいるのでしょうか? その理由は、React では HTML のネイティブ イベントがカプセル化され、合成イベントと呼ばれるためです。 **そのため、React 独自のライフサイクルや合成イベントでは、 isBatchingUdatesの値を制御し、その値を使用してページを更新するかどうかを判断できます。ホスト環境によって提供されるネイティブ イベント (つまり、非合成イベント) では、 isBatchingUpdatesの値を false に設定できないため、更新はすぐに実行されます。

☆setStateは同期シナリオではありませんが、特別なシナリオではReactによって制御されません**

要約する

setState は単純な同期関数でも非同期関数でもありません。同期と非同期のパフォーマンスの違いは、呼び出しシナリオの違いに反映されます。これは、React のライフサイクルおよび合成イベント内で非同期関数として動作します。 DOM のネイティブ イベントなどの非合成イベントでは、同期関数として表示されます。

以上がReact setStateデータ更新メカニズムの詳細な説明です。React setStateデータ更新メカニズムの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • React 純粋関数コンポーネント setState がページ更新を更新しない問題の解決方法
  • React における同期および非同期 setState の問題のコード分析
  • react setStateの詳細な説明
  • ReactでのsetStateの使用と同期と非同期の使用
  • ReactのsetStateコールバック関数の詳細な説明
  • React.setStateを使用する際に注意すべき3つのポイントについて簡単に説明します。
  • ReactのsetStateソースコードの詳細な研究
  • React で複数の setStates が何回呼び出されるのでしょうか?

<<:  JDBC が MySQL に接続して中国語を処理するときに文字化けする問題の解決方法の詳細説明

>>:  Ubuntu 18.04 向け VMware Tools のインストールと構成のチュートリアル

推薦する

MySQL の挿入ステートメントの使用実体験

目次1. 挿入のいくつかの構文1-1. 通常の挿入文1-2. 挿入または更新1-3. 挿入または交換...

Vue ページをリフレッシュするために provide と injection を適用する

目次方法1: 関数を直接呼び出す方法2: provide / inject (静的更新) を使用する...

CSS で 3 列レイアウトを実装するいくつかの方法と利点と欠点

序文3 列レイアウトは、その名前が示すように、両側が固定され、中央が適応します。実際の開発では、3 ...

HTML 基本要約推奨事項 (タイトル)

HTML: タイトル見出しは <h1> - <h6> などのタグによって定...

Jenkins を通じて None のイメージを定期的にクリーンアップする方法

序文継続的なコード配信のプロセスで、Jenkins を利用して Docker イメージを作成すると、...

Nginx イントラネット スタンドアロン リバース プロキシの実装

目次1 Nginxのインストール2 Nginxの設定3 ホストファイルを変更する4 テストNginx...

CSS3の3D効果を使って立方体を作成する

CSS3 の 3D 効果を使用して立方体を作成する方法を学ぶと、3D シーンの回転と変位のプロパティ...

Nginx http ヘルスチェック構成プロセス分析

パッシブチェックパッシブ ヘルス チェックでは、NGINX と NGINX Plus はイベントの発...

Vue3.0でカスタム命令を書くための簡単な手順

序文Vue には、v-if、v-bind、v-on などの豊富な組み込みディレクティブが用意されてい...

Linux に起動方法を追加する (サービス/スクリプト)

システムの起動時に読み込む必要がある設定ファイル/etc/profile、/root/.bash_p...

TypeScript のクラス

目次1. 概要2. シンプルなクラスを定義する3. 継承4. public、private、prot...

英語の単語の出現頻度を数えるtrコマンドの魔法

置換を削除したり文字列を削除したりできる tr コマンドは、誰もがよく知っています。 英語では、英語...

Linux の一般的なコマンド chmod を使用して、ファイルの権限 777 と 754 を変更します。

よく使用されるコマンドは次のとおりです。 chmod 777 文件或目錄例: chmod 777 /...

Vue3.0 は虫眼鏡効果のケーススタディを実装します

達成される効果は、固定ズームが 2 倍になり、マウスが左側の画像領域に入るとマスク レイヤーが表示さ...

Vue+element はローカル検索機能付きのドロップダウン メニューを実装します

必要:バックエンドは配列オブジェクトを返し、それがフロントエンドで配列に結合されます。配列は名前に従...