zishu's blog

zishu's blog

一个热爱生活的博主。https://zishu.me

なぜキーが必要なのですか?

以前に述べたように、React でリストをレンダリングする際には、各データに key 値を付与し、確定的な識別子を与える必要があります。そして、識別子を付与する方法についても詳しく説明しましたが、なぜこれを行う必要があるのでしょうか?

React でリストをレンダリングする方法は?

デフォルトの条件下では、DOM ノードの子要素を再帰的に処理する際、React は 2 つの子要素のリストを同時に走査します。差異が生じると、mutation が生成されます。

子要素リストの末尾に要素を追加する場合、更新のオーバーヘッドは比較的小さくなります。例えば:

<ul>
  <li>first</li>
  <li>second</li>
</ul>

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

React は最初に 2 つの <li>first</li> に対応するツリーをマッチングし、次に 2 番目の要素 <li>second</li> に対応するツリーをマッチングし、最後に 3 番目の要素の <li>third</li> ツリーを挿入します。

もし単純に新しい要素を表頭に挿入するだけであれば、更新のオーバーヘッドは比較的大きくなります。例えば:

<ul>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

<ul>
  <li>Connecticut</li>
  <li>Duke</li>
  <li>Villanova</li>
</ul>

React は <li>Duke</li><li>Villanova</li> を保持すべきだと認識せず、すべての子要素を再構築します。この状況はパフォーマンスの問題を引き起こします。

key

上記の問題を解決するために、React は key 属性をサポートしています。子要素が key を持つ場合、React は key を使用して元のツリーの子要素と最新のツリーの子要素をマッチングします。以下の例では、key を追加することで以前の非効率な変換が効率的になります:

<ul>
  <li key="1">Duke</li>
  <li key="2">Villanova</li>
</ul>

<ul>
  <li key="0">Connecticut</li>
  <li key="1">Duke</li>
  <li key="2">Villanova</li>
</ul>

これで React は、'0' key を持つ要素が新しい要素であり、'1'および'2' key を持つ要素は単に移動しただけであることを理解します。

実際のシナリオでは、key を生成することは難しくありません。表示する要素にはすでに一意の ID がある場合が多く、そのため key はデータから直接抽出できます:

<li key={item.id}>{item.name}</li>

上記の状況が成立しない場合は、モデルに ID フィールドを追加するか、一部の内容をハッシュ値として使用して key を生成できます。この key は全体で一意である必要はありませんが、リスト内では一意である必要があります。

最後に、要素の配列内のインデックスを key として使用することもできます。この戦略は、要素が再配置されない場合に適していますが、順序が変更されると diff が遅くなります。

インデックスに基づくコンポーネントを再配置する際、コンポーネントの状態にいくつかの問題が発生する可能性があります。コンポーネントインスタンスは key に基づいて更新および再利用されるかどうかが決まるため、key がインデックスである場合、順序を変更すると現在の key が変更され、非制御コンポーネントの状態(例えば入力ボックス)が互いに干渉し、予期しない変化を引き起こす可能性があります。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。