React公式ドキュメントを読む19 配列データをリスト描画する

前回からの続きですが、このページだけ読んでも分かる内容になっています。 今回読むReact公式ドキュメントは「リストと key」ページの前半です。

今回は、Reactで配列データをリストとしてレンダリングする方法を見ていきます。例えば、配列に入ったメニュー項目をli要素として描画するなど、使用頻度の高い書き方です。

JavaScriptのmap()関数で配列データを操作

Reactでリスト表示をする場合、一般的には配列を利用します。以下のコードでは、JavaScriptのmap()関数を使って配列データを操作しています。

// 配列データ
const numbers = [1, 2, 3, 4, 5];

/*
JavaScriptのmap()関数を使って配列numbersを操作したものを
配列listItemsとして格納
*/
const listItems = numbers.map((number) =>
  <li>{number}</li>
);

// DOMへレンダリング
ReactDOM.render(
  <ul>{listItems}</ul>,
  document.getElementById('root')
);

上記のサンプルソースをHTMLファイルにしたものが以下です。

https://programming-world.net/sample/react_doc/lists1-1.html

上記コードでは、 JavaScriptのmap()関数 を使って元の配列 numbers を操作したものを、新しい配列 listItems として格納しています。配列 listItems は、<li>~</li>で整数を囲んだものとなります。

そして、DOMへレンダリングする際に、<ul>~</ul>で配列 listItems を囲んだものを要素として出力しています。Reactでは、中括弧 {} で囲むことで、JSXのなかに任意の式を埋め込むことができますが、配列もそのまま埋め込めます。

JavaScriptのmap()関数について

ここで、JavaScriptのmap()関数について確認しておきましょう。 JavaScriptのmap()関数は、配列データを操作する際に使用するメソッドです。配列の各要素に対して何らかの処理をした結果を、新しい配列として返します。

以下のコードでは、map()関数を使用して、配列 numbers の各要素の値を 2 倍にした結果を、新しい配列 doubled に格納しています。

//元の配列 numbers
const numbers = [1, 2, 3, 4, 5];
 
//map()関数による操作結果を、新しい配列 doubled に格納
const doubled = numbers.map(
  //配列の各要素を2倍にする
  function(number) {
    return number * 2;
  }
);

//コンソールに [2, 4, 6, 8, 10] と出力されるはず
console.log(doubled);

上記コードを実行すると、コンソールに [2, 4, 6, 8, 10] と出力されます。

上記のコードは、アロー関数を使って書くこともできます。以下のコードは、上記コードと等価です。

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(
  (number) => number * 2
);
console.log(doubled);

配列を受け取って要素のリストを出力するコンポーネントを作る

配列を受け取って要素のリストを出力するコンポーネントを作ってみましょう。

作りたいのは、[1, 2, 3, 4, 5]という内容の配列データをpropsで受け取って、<ul>や<li>タグで囲まれた要素のリストを返すコンポーネントです。

// NumberListコンポーネント
function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li>{number}</li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

// 配列データ
const numbers = [1, 2, 3, 4, 5];

// レンダリング
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

上記のサンプルソースをHTMLファイルにしたものが以下です。

https://programming-world.net/sample/react_doc/lists1-2.html

このコードを実行すると、期待した結果が表示されるのですが、コンソールを確認してみると、何やら警告が出ているようです。以下は、Chromeのデベロッパー ツールでコンソールに表示される警告内容です。

警告:リスト内の各子には、一意の "key" プロップが必要です。
NumberList の render メソッドを確認してください。

警告を読んでみると、「NumberList コンポーネントで生成されるli要素には、一意の”key”が必要です」と言っているようです。

ちなみに、 Chromeのデベロッパー ツールでコンソール は、Chrome画面左上の [︙] アイコン → [その他のツール] → [デベロッパー ツール] で表示されます。

Reactが要素を識別するための“key”

さて、警告には「NumberList コンポーネントで生成されるli要素には、一意の”key”が必要です」とありますが、 “key” とは一体なんでしょうか?

結論を言えば、 “key” とは 、どの要素が追加・変更・削除されたのかを React が識別するためのものです。Reactでは、配列データからリストなどの要素を生成する場合、Reactが識別できるように生成される各要素に一意の key を割り当てる必要があります。

上のコードで言えば、生成されるそれぞれのli要素にkeyを割り当ててやる必要があります。以下は、keyを割り当てた例です。

// NumberListコンポーネント(各li要素にkeyを割り当て)
function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li key={number.toString()}>
      {number}
    </li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

// 配列データ
const numbers = [1, 2, 3, 4, 5];

// レンダリング
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

上記のサンプルソースをHTMLファイルにしたものが以下です。

https://programming-world.net/sample/react_doc/lists1-3.html

今度は、コンソールに警告は出ていません。

まとめ

今回は、 Reactで配列データをリスト描画する方法について解説しました。

リスト項目として生成される要素には、Reactが識別できるようにそれぞれにkeyを割り当てる必要がありますが、次回は key についてもう少し詳しく解説します。

次回へ続きます。