ReactのPropsの簡単な比較

ReactのPropsの簡単な比較

先週面接に行ったとき、面接官からPureComponentpropsを比較する方法を尋ねられました。その概念はすでに頭に記憶されていたので、私が最初に口走ったのは「浅い比較」でした。その後、面接官から浅い比較のやり方を尋ねられましたが、答えることができませんでした。

週末を利用して、ソース コードでどのように実装されているかを確認してください。

クラスコンポーネントのプロパティ比較

クラス コンポーネントを更新する必要があるかどうかは、shouldComponentUpdate メソッドを実装する必要があります。一般的に、PureComponent を継承する場合は、デフォルトで浅い比較が実装されます。

// ReactBaseClasses.js
関数 ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;

/**
 * sCU のデフォルトの浅い等価性チェックを備えた便利なコンポーネント。
 */
関数 PureComponent(props, context, updater) {
  プロパティ
  this.context = コンテキスト;
  // コンポーネントに文字列参照がある場合は、後で別のオブジェクトを割り当てます。
  this.refs = 空のオブジェクト;
  this.updater = アップデーター || ReactNoopUpdateQueue;
}

ComponentDummy は、コンポーネントのプロトタイプをクラス化して作成します。
pureComponentPrototype.コンストラクタ = PureComponent;
// これらのメソッドの余分なプロトタイプジャンプを回避します。
オブジェクトに pureComponentPrototype を割り当てます。
pureComponentPrototype.isPureReactComponent = true;

PureComponentの実装は上記の通りです。以前はshouldComponentUpdateメソッドを宣言するとデフォルトで実装されると思っていましたが、実はデフォルトメソッドは存在しません。

次に、 shouldComponentUpdateメソッドの呼び出しを見てみましょう。

// ReactFiberClassコンポーネント.js
関数 checkShouldComponentUpdate(
  進行中、
  俳優、
  古いProps、
  新しいプロパティ、
  古い状態、
  新しい状態、
  次のコンテキスト、
){
  const インスタンス = workInProgress.stateNode;
  // インスタンスが shouldComponentUpdate を実装している場合は、それを呼び出した結果を返します。if (typeof instance.shouldComponentUpdate === 'function') {
    const shouldUpdate = instance.shouldComponentUpdate(
      新しいプロパティ、
      新しい状態、
      次のコンテキスト、
    );
    shouldUpdate を返します。
  }

  // PureReactComponent を使用する場合の浅い比較 if (ctor.prototype && ctor.prototype.isPureReactComponent) {
    戻る (
      !shallowEqual(古いプロパティ、新しいプロパティ) || !shallowEqual(古い状態、新しい状態)
    );
  }

  true を返します。
}

実際には PureReactComponent 用に別途 shouldComponentUpdate メソッドが記述されていないことがわかりますが、比較中に浅い比較の結果が返されます。

浅い比較の答えはすべて shallowEqual メソッドにあります。

浅い同等の浅い比較

// 浅いイコール.js
関数 shallowEqual(objA: mixed, objB: mixed): ブール値 {
  // 同じオブジェクトがtrueを返す
  オブジェクトがobjA、objBである場合
    true を返します。
  }

  // オブジェクトまたは null でない場合は false を返します
  もし (
    objA の型 !== 'オブジェクト' ||
    objA === null ||
    objB の型 !== 'オブジェクト' ||
    objB === null
  ){
    false を返します。
  }

  定数 keysA = Object.keys(objA);
  定数 keysB = Object.keys(objB);

  // キーの数が異なる場合はfalseを返す
  (keysAの長さ!==keysBの長さ)の場合{
    false を返します。
  }

  // 対応するキー値が同じでない場合はfalseを返す
  (i = 0 とします; i < keysA.length; i++) {
    もし (
      !hasOwnProperty.call(objB, keysA[i]) ||
      !Object.is(objA[keysA[i]], objB[keysA[i]])
    ){
      false を返します。
    }
  }

  true を返します。
}

shallowEqualメソッドの原理は非常にシンプルです

  1. まず、2 つが同じオブジェクトであるかどうかを判断します。
  2. 両方の値がオブジェクトではないか、または null であるかを判断します。
  3. 2 つのキーの長さを比較します。
  4. 2つのキーに対応する値が同じかどうかを判断します。

原理は、とても単純な比較だということがわかりました。面接中にソースコードを暗唱できれば、給料は上がるのでしょうか?

機能コンポーネントの簡単な比較

関数コンポーネントの浅い比較メソッドは、React.memo メソッドを使用して実装されます。

// ReactMemo.js
関数メモ<Props>をエクスポートします(
  タイプ: React$ElementType、
  比較しますか?: (oldProps: Props, newProps: Props) => ブール値、
){
  定数要素タイプ = {
    $$typeof: REACT_MEMO_TYPE、
    タイプ、
    比較: 比較 === 未定義? null: 比較、
  };
  要素タイプを返します。
}

React.memo メソッドは、2 番目のパラメータとして比較関数を渡すこともサポートしています。

内部処理では、実際には、後続の型判断を容易にするために、$$typeof を REACT_MEMO_TYPE として手動で ReactElement を作成します。

React.memo コンポーネントの作成はもう少し複雑です。2 番目のカスタム比較関数を渡すことができるため、実際には内部的に 2 種類の Fiber ノードとして定義されます。

  • 比較関数が渡されないものは SimpleMemoComponent です。
  • カスタム比較関数に渡すのは MemoComponent です。

ただし、Props の実際の比較は同じであり、比較にはデフォルトで shallowEqual メソッドが呼び出されます。

シンプルメモコンポーネントの更新

もし (
  shallowEqual(前のプロパティ、次のプロパティ) &&
  現在の参照 === 進行中の参照
){
	// ...
}

メモコンポーネントの更新

// ...
compare = Component.compare; とします。
compare = compare !== null ? compare : shallowEqual;
if (比較(prevProps, nextProps) && current.ref === workInProgress.ref) {
  bailoutOnAlreadyFinishedWork(current、workInProgress、renderLanes) を返します。
}
// ... 

なぜ2つに分かれているのかはよく分かりませんが、おそらくアップデートのスケジュールに関係しているのでしょう。

SimpleMemoComponent の Fiber ノードは、実際には名前が変更された関数コンポーネントに相当します。プロセスは関数コンポーネントに直接進みますが、MemoComponent はシェルで覆われています。まずシェルを剥がして子 Fiber ノードを生成し、子 Fiber ノードの判断に基づいて関数コンポーネントに進む必要があります。

上記はPropsの簡単な分析です。

以上がReactにおけるPropsの浅い比較の詳細な内容です。ReactにおけるPropsの浅い比較の詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Reactのコンテキストとプロパティの説明
  • Reactの3つの主要属性におけるpropsの使用の詳細な説明
  • ReactのRender Propsパターンについて話す
  • ES6 クラスチェーン継承、インスタンス化、React Super (props) 原則の詳細な説明
  • React Propsの原理を理解するのに役立つ記事

<<:  MySQL 5.7を完全にアンインストールするための詳細な手順

>>:  Centos サーバーで nginx を設定する方法の例

推薦する

Ubuntu システムにおけるネットワーク構成ファイルの分析と説明

今日は奇妙なネットワーク問題に遭遇しました。調査プロセスといくつかの構成状況を記録し、Linux で...

MAC 上の MySQL の初期パスワードを忘れた場合の対処方法

MACでMySQLの初期パスワードを忘れた問題を解決する方法を参考までに共有します。具体的な内容は次...

MySQL はどのようにしてマスターとスレーブの同期を実現するのでしょうか?

マスタースレーブ同期 (マスタースレーブレプリケーションとも呼ばれる) は、マスタースレーブデータの...

HTML テーブルタグチュートリアル (13): 内部境界スタイル属性ルール

RULES を使用すると、テーブルの内部境界のスタイルを制御できます。基本的な構文<TABLE...

HTML検証 HTML検証

HTML 検証はHTML 検証を指します。これは、HTML ドキュメントを分析し、標準の HTML ...

CentOS7にJDK8をrpmモードでインストールする

CentOS 7が正常にインストールされると、OpenJDKのJREがデフォルトでインストールされて...

MySQLの文字セットを変更する方法

1. MySQLの文字セットを確認する '%char%' のような変数を表示します。...

docker ベースで Prometheus+Grafana を構築する手順の詳細説明

1. プロメテウスの紹介Prometheus は、もともと SoundCloud によって開発された...

HTML ファイルにファイルの内容を含める方法の概要

フォーラムでは、ネットユーザーから「HTML ファイル内の別の HTML ファイルの内容を読み取るこ...

HTML 中国語文字エンコード標準の概要

HTML では、Web ページで使用されるエンコーディングを指定する必要があります。一般的な指定方法...

Element PlusはAffixを実装します

目次1. コンポーネントの紹介2. ソースコード分析2.1 テンプレート2.2 スクリプト2.3 実...

CSS を使用して画像の色を変更する 100 の方法 (収集する価値あり)

序文「画像処理というと、PhotoShop などの画像処理ツールを思い浮かべることが多いです。フロン...

MySQLで自動作成時間と変更時間を設定する方法の例

この記事では、MySQL の自動作成時刻と変更時刻を設定する方法について説明します。ご参考までに、詳...

Vue3でアイコンを使用する2つの例

目次1. SVGを使用する2. fontAwesomeを使用する3 ソース4 結論テクノロジースタッ...