Reactを勉強し始めた方にとってはデータをリストで表示させる時には「key」を持たせる必要があるということは知っていると思います。
本記事ではなぜkeyが必要なのか、keyがなければどのような挙動になるのかを動画などを用いて解説します😌
では早速解説を始めていきます。
結論:keyを使うことで情報更新の必要な箇所を絞らせ効率的に更新できるようになる
これ以降は結論に至るまでの検証内容となります。
Reactでコンポーネントを使い、リストでデータを表示させるとき”何もしなければ”下記のようなエラーが出ます。
Reactはデータをリストで表示させるという観点では、特別なコンセプト持っています。
それは「Reactがリスト内のデータの更新や表示をバグやWebパフォーマンスを落とすことなく効率的にできるようにすることを明確にする必要がある」です。
上記のエラーはこのコンセプトに反しているために起きたエラーです。
では具体的に今の状態ではどんな問題があるかをみてみましょう。
先に今回のサンプルコードをお見せします。(見るだけで大丈夫です)
import React, { useState } from 'react';
import './ReactDev.css';
const DUMMY_DATA = [
{ id: 'd1', type: 'Manga' },
{ id: 'd2', type: 'Dictionary' },
{ id: 'd3', type: 'Novel' },
];
const ReactDev = () => {
const [list, setList] = useState(DUMMY_DATA);
const [enteredType, setEnteredType] = useState('');
const typeChangeHandler = (event) => {
setEnteredType(event.target.value);
};
const addList = (e) => {
e.preventDefault(e);
const data = { type: enteredType };
const saveData = {
...data,
id: Math.random().toString(),
};
setList((prevList) => {
return [saveData, ...prevList];
});
setEnteredType('');
};
const dataList = list.map((data) => (
<li>
<h2>{data.type}</h2>
</li>
));
return (
<div className="container">
<form onSubmit={addList}>
<label htmlFor="type"></label>
<input
id="type"
type="text"
value={enteredType}
onChange={typeChangeHandler}
/>
<button type="submit">Add List</button>
</form>
<ul>{dataList}</ul>
</div>
);
};
export default ReactDev;
実装内容はざっくりと下記の内容です。
①DUMMY_DATAをリスト表示させる
②フォームにテキスト入力
③テキスト内容をリストの一番上に表示させる
こんな感じです↓
ここからが重要なのですが、実際に動かしてこの挙動をChromeの検証ツールで確認してみます。
一番下のリストタグに注目してください。
リストタグが一番下に一瞬点滅して追加されました。
Chromeの検証モードでは情報が追加もしくは更新された時に点滅するようになっています。
しかし新しく追加したテキスト情報はリストの一番上にきています。
なぜでしょう?
この現象は検証ツールでリストタグを広げた状態で見ると理解しやすくなります。
先ほどと同様に一番下にリストタグが点滅しながら追加されたのと、さらに各リストタグの子要素である全てのh2タグが点滅し情報が更新されました。
つまり現在のソースコードでリスト内のデータを更新しようとすると、次の2つのステップが発生します。
STEP1:リストの一番下にリストタグを新しく追加する
STEP2:新しいリストをもとに各h2タグの中身を上から順番にデータを書き換える
この方法でデータを読み取るのは効率的ではありませんが、仕方ありません。
配列データが一つ増えただけとはいえ、”何もしなければ”、Reactは新たな配列とみなし頭からデータを読みとりにいき変更点の更新を行います。
しかし、Reactには情報更新の必要な箇所を絞らせ効率的に更新する方法があります。
それが「key」です。
keyを使うことで、Reactにどこに新しいデータが追加されるかを教えることができ、各データを個別で把握させることができるのです。
注意点としてそれぞれのkeyにはユニークな値を入れなければなりません。
keyを記述した新しいコードはこちらです。(見るだけでOKです)
import React, { useState } from 'react';
import './ReactDev.css';
const DUMMY_DATA = [
{ id: 'd1', type: 'Manga' },
{ id: 'd2', type: 'Dictionary' },
{ id: 'd3', type: 'Novel' },
];
const ReactDev = () => {
const [list, setList] = useState(DUMMY_DATA);
const [enteredType, setEnteredType] = useState('');
const typeChangeHandler = (event) => {
setEnteredType(event.target.value);
};
const addList = (e) => {
e.preventDefault(e);
const data = { type: enteredType };
const saveData = {
...data,
id: Math.random().toString(),
};
setList((prevList) => {
return [saveData, ...prevList];
});
setEnteredType('');
};
const dataList = list.map((data) => (
<li key={data.id}>
<h2>{data.type}</h2>
</li>
));
return (
<div className="container">
<form onSubmit={addList}>
<label htmlFor="type"></label>
<input
id="type"
type="text"
value={enteredType}
onChange={typeChangeHandler}
/>
<button type="submit">Add List</button>
</form>
<ul>{dataList}</ul>
</div>
);
};
export default ReactDev;
変更点はこちらです。
各データのkeyをユニークにしているのはこの部分です。
では実際にkeyを入れることでどのように変わるかみてみましょう。
今回は一番上のリストタグの上に新たなリストタグが点滅して追加され、それ以外の要素は点滅しなくなりました。
これはつまり新たなリストタグだけが追加されたということです。
また最初にできてたエラー文はなくなりました。
keyを使っていない時との比較はこちらです。
keyなしの更新箇所↓
keyありの更新箇所↓
更新を必要な箇所に絞ることによって無駄な変更をなくしサイトのパフォーマンスを最適化できます。
今回はデータ量が少ない例で行いましたが、大規模なアプリではデータ量も多くなるためkeyを使わなければアプリのパフォーマンスにも影響が出てしまいます。
そもそもデータをリストで表示させるときにkeyなしではエラーで出てしまうので、ぜひ使っていきましょう。
今回の記事が少しでも皆さんの理解につながっていると幸いです。
最後に
一般のエンジニアがどのように言語(今回はフレームワークになりますが)を学習し、つまずき、乗り越えていっているのかを垣間見えるようにしていこうと思います。
少しでもこれからプログラミングを学ぼうと考えている方の為になる発信をできれば思いますので、温かい目で見てもらえると嬉しいです。
今回学習のメイン教材として使うのは、Udemyのコースになります。
ベストセラー取得