1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

コンポーネントのkeyにarray index は使わない

Posted at

最近知って残しておきたいことのメモです。

💡react component のkey にarray index は使用しない

先輩のアドバイスの表現をお借りすると...

配列のindexをコンポーネントの key に指定すると、
それは本質的に一意な値ではないため
配列の変更に伴って不要な再レンダリングが発生するなど非効率
⇒ 避けるべき実装である

(参考)https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-array-index-key.md

これを聞いてどうにか頭を整理した結果↓

  • Reactの仮想DOMの差分でレンダリングする特性に関連している
  • 配列のindexは、例えばある要素が削除されたり先頭に追加されると、他の要素のindexにも変化が起こる(各要素のindexがひとつ前にずれたり後ろにずれたり)
    --->>> 上記の2点から、本来は同じ要素なのに、前回のレンダリングからindexが変わっていると、違う要素だとReact側が認識し、不要なレンダリングが行われたりパフォーマンスが低下しうる。

以下、eslint-plugin-reactのgithubから拝借

// よくない例
things.map((thing, index) => (
  React.cloneElement(thing, { key: index })
));
// よい例
things.map((thing) => (
  React.cloneElement(thing, { key: thing.id })
));

これに則って実装をしようとしたとき、シンプルな文字列の配列とかだとindexしかkeyに指定できるものない....とも思ったりしたのですが、それなら指定できる一意になるプロパティを追加しちゃえばいいのかな?と思い、文字列の配列をオブジェクトの配列に変形させたりしてみました。

// 元の配列と処理
const prefectures = ['東京', '埼玉', '千葉', '神奈川']

prefectures.map((prefecture, index) => (
  React.cloneElement(prefecture, { key: index })
));

// 修正した配列と処理
const prefectures = [
  { id: 1, name: '東京' },
  { id: 2, name: '埼玉' },
  { id: 3, name: '千葉' },
  { id: 4, name: '神奈川' }
]

prefectures.map((prefecture) => (
  React.cloneElement(prefecture, { key: prefecture.id })
));

ESLintのルールで、keyにindexを渡すことを検出するには↓

 // 省略
 "rules": {
    "react/no-array-index-key": "warn" // または"error"
  }

最近は「処理効率の良いコード」に興味。
どうやってそれの学びを深めるのかもよくわからないですが
こうやってひとつひとつ吸収していけたらと思っています。

🙏最後に🙏
初学者のメモレベルですが、もし誤認があったり誤解を与えるような表現がありましたら、お手数ですがご指摘をいただけますと幸いです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?