ReactのKey!まだインデックスを使っていますか?


ゴムを開発する際、特に早期にこのような警告文を多く見たことがあるかもしれません.

Warning: Each child in a list should have a unique "key"prop. !!!
mapなどを使用して構成部品を繰り返し作成する場合、キー値を指定しない警告です.
では、なぜこのキー値が必要なのでしょうか.

メタツリー


コンポーネントのステータスまたはプロパティが変化するたびに、応答はrender関数を呼び出し、render関数は新しい応答要素を返し、既存の要素ツリーと比較し、新しい変更点のみを再レンダリングします.
keyアトリビュートを使用してO(N)の時間的複雑さで2つのツリーを比較する場合、リアクターはkeyアトリビュートを使用し、サブエレメントを繰り返しレンダリングする場合にkeyを明示的に使用します.
つまり、ツリーを比較するときにキー値を比較し、キー値が異なるとレンダリングが再開されます.キー値によって追加されたデータと要素を配置することもできます.


キーをインデックスとして使用する場合


後にデータを追加

import { useState } from "react";

const StudyPage = () => {
    const [data,setData]= useState([
        {
            id: 1,
            name: "나름"
        },
        {
            id:2,
            name: "콘스트"
        },
        {
            id:3,
            name:'조이'
        }
    ]); 

    const clickButton = () => {
        setData([...data,{id:4,name:"합체"}])
        console.log(data)
    }
    return(
        <>
            <button onClick={clickButton}> 추가 </button>
            <ul>
                {data?.map((item,index)=><li key={index}>{item.name}</li>)}
            </ul>
        </>
    )
}

export default StudyPage;
まず、このような状況を仮定し、例を挙げて説明します.
key値をindexとして使用し、後に新しいデータを貼り付けます.

最後のデータのみがレンダリングされているのが見えますか?これで最後のデータを追加しても問題ありません.

前にデータを追加


問題は、前にデータを追加することです.
    const clickButton = () => {
        setData([{id:4,name:"합체"},...data])
        console.log(data)
    }
このようにclickButton関数を修正すると、前に新しいデータが追加されますよね?


次に、レンダリング全体が表示されます.
  <ul>
      <li key=1>나름</li>
      <li key=2>콘스트</li>
      <li key=3>조이</li>
  </ul>
前にデータが追加されたため、インデックスが変わりました.
  <ul>
      <li key=1>합체</li>
      <li key=2>나름</li>
      <li key=3>콘스트</li>
      <li key=4>조이</li>
  </ul>
key値が変更されたため、反応で異なる再レンダリングが行われていることがわかります.
これは、キー値を変更しない唯一の値に設定する必要があることを意味します.
だから私が考えているのは、1次元でitemをキー値に入れるとデータが変わらないので再レンダリングできないのではないでしょうか.そう思うよ

key値にitemデータ自体が加わった!

<>
	<button onClick={clickButton}> 추가 </button>
	<ul>
        	{data?.map((item)=><li key={item}>{item.name}</li>)}
    </ul>
</>
これで修正しました!結果はね.

まったく.全体がレンダリングされました.もう一つの警告メッセージがあります.

警告:オブジェクトオブジェクト(Object)という名前の同じキーを持つ2つの子が表示されます.コンポーネントが更新の間にIDを保持する鍵が一意であることを確認します.ユニークでないキーは、サブボディの繰り返しおよび/またはスキップに使用できます.この操作はサポートされておらず、将来のバージョンで変更される可能性があります.
すなわち、react keyは無条件にオブジェクトを文字列に変換するので、オブジェクトを文字列化すると、オブジェクトオブジェクトは[objectObject]となり、すべてのキー値が同じになる.次に、reactを追加する正確な位置が見つからないため、領域全体を再レンダリングします.

解決する


通常、サーバからデータを受信すると、データには一意のidx値があります.この値を使用すると、問題が解決しやすくなります.
例で使用するデータフォーマットは、次のとおりです.
[
        {
            id: 1,
            name: "나름"
        },
        {
            id:2,
            name: "콘스트"
        },
        {
            id:3,
            name:'조이'
        }
]
したがって,idは各データの固有値であり,固有idxである.このid値をキー値として指定すると、
        <>
            <button onClick={clickButton}> 추가 </button>
            <ul>
                {data?.map((item)=><li key={item.id}>{item.name}</li>)}
            </ul>
        </>
そうでしょう.このコードの実行結果から見ると

追加されたクリーンな部分だけがデータが再ロードされることを知っています.
このキーの値は、グローバルで一意である必要はありませんが、パフォーマンスを損なうことなく、同じ重複する兄弟要素で一意である必要があります.