Reactのkeyとは?
Reactで配列をmap()して一覧表示するときは、それぞれの要素にkeyを指定します。
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
keyは、Reactが「どの要素がどのデータに対応しているのか」を判断するための目印です。
公開日:
Reactで配列をmap()して一覧表示するときは、それぞれの要素にkeyを指定します。
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
keyは、Reactが「どの要素がどのデータに対応しているのか」を判断するための目印です。
まず、keyを付けずに配列を一覧表示してみます。
const items = [
{ id: 101, name: "さくら" },
{ id: 102, name: "たろう" },
{ id: 103, name: "すみれ" },
];
function App() {
return (
<ul>
{items.map((item) => (
<li>{item.name}</li>
))}
</ul>
);
}
export default App;
画面には一覧が表示されますが、開発者ツールのConsoleを見ると、keyに関する警告が表示されます。
Reactは一覧を表示できないわけではありません。
ただし、それぞれの要素を正しく識別するために、keyを指定するよう求めています。
それぞれのデータが持っているidを、keyとして指定します。
const items = [
{ id: 101, name: "さくら" },
{ id: 102, name: "たろう" },
{ id: 103, name: "すみれ" },
];
function App() {
return (
<ul>
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
export default App;
idは、それぞれのデータを区別するための値です。
Reactはこの値を使って、前回の表示と今回の表示で「同じ要素かどうか」を判断しやすくなります。
一覧の内容がずっと同じなら、keyの必要性は分かりにくいかもしれません。
しかし、追加・削除・並び替えが起きると、keyが重要になります。
たとえば、次の3件がこの順番で表示されているとします。
ここで順番を「すみれ、さくら、たろう」に並び替えても、idはそれぞれのデータに付いたまま変わりません。
Reactはkeyを使うことで、順番が変わっても「どの要素がどのデータに対応しているのか」を正しく判別できます。
map()では、配列のインデックスを表すindexを受け取ることもできます。
const items = [
{ id: 101, name: "さくら" },
{ id: 102, name: "たろう" },
{ id: 103, name: "すみれ" },
];
function App() {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item.name}</li>
))}
</ul>
);
}
export default App;
この書き方でも警告は消えます。 ただし、追加・削除・並び替えがある一覧では、indexをkeyにするのは避けた方がよいです。
indexは「そのデータ自身の識別情報」ではなく、「配列のインデックス」を表す値だからです。
たとえば、「さくら、たろう、すみれ」の順に並んでいるとき、それぞれのindexは0、1、2です。
ここから「すみれ、さくら、たろう」の順に並び替えると、同じindexが別のデータに割り当てられます。
たとえば各行に入力欄やチェック状態を持つコンポーネントがある場合、indexをkeyにしていると、
追加や並び替えのあとに入力内容やStateが意図しないデータと対応してしまうことがあります。
一方で、内容も順番も変わらない固定的な一覧では、indexを使っても問題にならない場合があります。
ただし、データに適切なidがあるなら、基本的にはそのidを使う方が分かりやすいです。
keyには、再レンダリングのたびに変わらない値を使う必要があります。
たとえば、次のようにmap()の中で毎回新しいIDを作るのは適切ではありません。
{items.map((item) => (
<li key={crypto.randomUUID()}>{item.name}</li>
))}
この書き方では、再レンダリングされるたびにkeyが変わります。
Reactから見ると、前回とは別の要素として扱われやすくなってしまいます。
IDが必要なら、データを作成するときに一度だけ付けて、その値を使います。
import { useState } from "react";
function App() {
const [items, setItems] = useState([]);
const handleAdd = () => {
const newItem = {
id: crypto.randomUUID(),
name: "新しいアイテム",
};
setItems((prevItems) => [...prevItems, newItem]);
};
return (
<div>
<button onClick={handleAdd}>追加</button>
<ul>
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
}
export default App;
この例では、アイテムを追加するときにidを作成し、その後は同じidを使い続けています。
keyは、同じ一覧の中で重複しない値を指定します。
たとえば、次のように同じ一覧の要素へ同じkeyを指定するのはNGです。
<ul>
<li key="1">さくら</li>
<li key="1">たろう</li>
</ul>
2つのliに同じkeyが指定されているため、Reactがそれぞれの要素を正しく識別できません。
一方、別の一覧であれば、同じkeyを使うことができます。
<ul>
<li key="1">さくら</li>
</ul>
<ul>
<li key="1">たろう</li>
</ul>
この場合は別々の一覧なので、どちらにkey="1"があっても問題ありません。
keyはアプリ全体で一意にする必要はありません。
ここまでは、map()からliなどの要素を1つ返し、その要素にkeyを指定してきました。
1件のデータにつき複数の要素を返したい場合は、Fragmentでまとめることがあります。
この場合は、map()から直接返すFragmentにkeyを指定します。
import { Fragment } from "react";
const items = [
{ id: 101, name: "さくら" },
{ id: 102, name: "たろう" },
{ id: 103, name: "すみれ" },
];
function App() {
return (
<dl>
{items.map((item) => (
<Fragment key={item.id}>
<dt>{item.name}</dt>
<dd>学習中</dd>
</Fragment>
))}
</dl>
);
}
export default App;
Fragmentの短縮記法<>...</>にはkeyを指定できません。
keyが必要な場合は、<Fragment key={...}>の形で記述します。
Fragmentの役割や短縮記法との違いについては、関連記事で詳しく解説します。
keyはReactが内部で使う特別な値なので、通常のpropsとは少し扱いが違います。
たとえば、次のようにkeyを指定しても、子コンポーネントでkeyをpropsとして受け取ることはできません。
function ItemRow({ item }) {
return <li>{item.name}</li>;
}
function App() {
const items = [
{ id: 101, name: "さくら" },
{ id: 102, name: "たろう" },
{ id: 103, name: "すみれ" },
];
return (
<ul>
{items.map((item) => (
<ItemRow key={item.id} item={item} />
))}
</ul>
);
}
export default App;
子コンポーネントでもIDを使いたい場合は、keyとは別にpropsとして渡します。
<ItemRow
key={item.id}
itemId={item.id}
item={item}
/>
いいえ。
keyはReactが一覧の要素を識別するために使う値で、指定しただけでは画面には表示されません。
一覧の追加・削除・並び替えがある場合は、配列のインデックスをそのままkeyにするのは避けた方がよいです。
データ自身を識別できるidなどを使いましょう。
逆です。 同じデータには、再レンダリング後も同じkeyが使われる必要があります。
keyは安定していることが大切です。
そこまでの一意性は必要ありません。 同じ一覧の中で重複しなければ大丈夫です。
Reactのkeyは、一覧の各要素をReactが識別するための値です。
map()で一覧表示するときは、それぞれの要素にkeyを指定するkeyには、データを一意に識別できる安定した値を使うkeyにするのは避けるkeyにしないkeyは同じ一覧の中で重複させないkeyは通常のpropsとして子コンポーネントへ渡されない「警告を消すためにkeyを書く」のではなく、「同じデータをReactが見分け続けられるようにkeyを書く」と考えるのがポイントです。