コンポーネントへのkeyの設定
Reactはいい感じにDOMの更新を行う都合で、動的に複数の子要素を作るときはkeyを割り当てる必要があります。なくても動きますが、ブラウザのコンソールにwarningが出てしまうため気持ちのいいものではありません。
最も遭遇する場面は、map
やfor
などのループで子コンポーネントを複数呼ぶときでしょう。この時、例えばChild
というコンポーネントを呼ぶとき(またはそれをラップする別の要素へ)key
属性とユニークな値を付与します。
また、key
属性はpropsで子コンポーネントには送れません。そのためkey
属性用の変数はkey
でええやろといった気持ちでpropsから受け取ろうとするとバグの原因になります。
また、その気持ちで子コンポーネントでPropsを受け取る時、keyを指定すると受け取る値はundefined
になります。使い方を間違って子で受け取ったkeyの値をkey属性に指定すると怒られます。
正しい例
※以下のコードではkeyに配列の中身の値を設定していますが、重複があったらとかインデックス的な値はよろしくないと言ったベストプラクティス系は無視してください
複数の要素を作るときにkeyを指定する
親コンポーネント
import Child from './child'
export const parent = () => {
const a = [1,2,3,4,5]
return (<>
{
a.map((e: number) => {
return <Child e={e} key={e} />
})
}
</>)
}
export default parent
子コンポーネント
import React from 'react'
type Props = {
e:number
}
export const child :React.FC<Props>= ({e}) => {
return <div>{e}</div>
}
export default child
間違い1
複数呼ばれる子コンポーネント側でkey
を指定する例
Warning: Each child in a list should have a unique "key" prop.
各要素にはユニークなkeyを設定しなさ〜いと言われます。
親コンポーネント
import Child from './child'
export const parent = () => {
const a = [1,2,3,4,5]
return (<>
{
a.map((e: number) => {
- return <Child e={e} key={e} />
+ return <Child e={e} />
})
}
</>)
}
export default parent
子コンポーネント
import React from 'react'
type Props = {
e:number
}
export const child :React.FC<Props>= ({e}) => {
- return <div>{e}</div>
+ return <div key={e}>{e}</div>
}
export default child
間違い2
keyを子要素で受け取って使った
Warning: child: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop.
props
でkey
を受け取れないのでundefined
ですよ。
親コンポーネント
import Child from './child'
export const parent = () => {
const a = [1,2,3,4,5]
return (<>
{
a.map((e: number) => {
return <Child e={e} key={e}/>
})
}
</>)
}
export default parent
子コンポーネント
import React from 'react'
type Props = {
e:number,
+ key:number
}
-export const child :React.FC<Props>= ({e}) => {
- return <div key={e}>{e}</div>
-}
+export const child :React.FC<Props>= ({e,key}) => {
+ return <div key={e}>{e}</div>
+}
export default child
気にしなくても動くことは動くんですけどね。