配列を一覧表示しよう

← 第4
Reactアプリ作成(JS編)5 / 15
6回 →

今回やること

前回は、JavaScriptのitemオブジェクトを使って、 一覧画面に1件分のデータを表示しました。

しかし、実際の一覧では1件だけではなく、 複数の「気になるもの」を表示したいですよね。

今回は、複数のデータを配列にまとめ、 map()を使ってテーブルへ一覧表示します。

あわせて、Reactで一覧を表示するときに必要になる keyについても確認します。

スポンサーリンク

複数のデータを配列で用意する

前回は、1つのitemオブジェクトを用意しました。

const item = {
  id: "sample-1",
  name: "はじめてのWebデザイン本",
  category: "本",
  status: "気になる",
  price: 2200,
  memo: "図が多くて読みやすそう",
};

今回は複数のデータを一覧表示したいので、 複数のオブジェクトをまとめて管理できる配列を使います。

itemitemsに変更し、 []の中に2つのオブジェクトを用意しましょう。

const items = [
  {
    id: "sample-1",
    name: "はじめてのWebデザイン本",
    category: "本",
    status: "気になる",
    price: 2200,
    memo: "図が多くて読みやすそう",
  },
  {
    id: "sample-2",
    name: "小さなサイドテーブル",
    category: "家具",
    status: "欲しい",
    price: 3500,
    memo: "部屋に置きやすそう",
  },
];

itemsは配列で、その中に2つのオブジェクトが入っています。

items 配列
↓
[
  { 1件目のデータ },
  { 2件目のデータ }
]

[]は配列を作るための記号、 その中にある{}は1件分のオブジェクトを作るための記号です。

まずは1件目をテーブルで表示する

前回は、1件分のデータをh3pで表示しました。

今回は複数件を一覧として並べるため、 HTMLのtableを使います。

まずは、items配列の1件目をテーブルに表示してみましょう。
配列では、先頭の要素を0として数えるため、1件目はitems[0]で取り出します。
たとえば、1件目の名前を取り出す場合は次のように書きます。

items[0].name

items[0]で配列の1件目のオブジェクトを取り出し、 .nameでその中のnameプロパティを取り出しています。

前回の一覧画面にあったh3pの部分を、 次のテーブルに置き換えましょう。

<table>
  <thead>
    <tr>
      <th>名前</th>
      <th>カテゴリ</th>
      <th>ステータス</th>
      <th>価格</th>
      <th>メモ</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>{items[0].name}</td>
      <td>{items[0].category}</td>
      <td>{items[0].status}</td>
      <td>{items[0].price}円</td>
      <td>{items[0].memo}</td>
    </tr>
  </tbody>
  </table>
気になるものリストをテーブルに1件表示した画面
気になるものリストがテーブルに1件表示されています。

では、2件目も表示するとしたらどうなるでしょうか。
2件目はitems[1]で取り出せるので、もう1つtrを書けば表示できます。

<tr>
  <td>{items[1].name}</td>
  <td>{items[1].category}</td>
  <td>{items[1].status}</td>
  <td>{items[1].price}円</td>
  <td>{items[1].memo}</td>
</tr>

2件ならこの方法でも書けますが、データが10件、20件と増えるたびに、同じ形のtrを追加するのは大変です。

そこで、配列のデータを1件ずつ処理できるmap()を使います。

map()で配列を1件ずつ処理する

map()はJavaScriptの配列メソッドです。
配列の要素を1件ずつ処理して、その結果から新しい配列を作れます。
今回は、この仕組みを使ってデータごとにtrを作ります。

まずは、JSXを使わないシンプルな形で見てみましょう。

items.map((item) => {
  // itemを使った処理
});

このコードでは、items配列の中から データを1件ずつ取り出し、 そのとき処理している1件をitemとして扱います。

items
↓
配列全体

map()
↓
配列の要素を1件ずつ処理する

item
↓
そのとき処理している1件分のオブジェクト

1回目の処理では、itemは 「はじめてのWebデザイン本」のオブジェクトになります。

item.name
// "はじめてのWebデザイン本"

2回目の処理では、itemは 「小さなサイドテーブル」のオブジェクトになります。

item.name
// "小さなサイドテーブル"

つまり、items[0]items[1]を 自分で書き分けなくても、 map()が配列のデータを順番に処理してくれます。

map()でtrを繰り返し作る

では、先ほど数値を指定していたtrの部分を、map()で繰り返して作ってみましょう。

tbodyの中を、次のように書き換えます。

<tbody>
  {items.map((item) => (
    <tr>
      <td>{item.name}</td>
      <td>{item.category}</td>
      <td>{item.status}</td>
      <td>{item.price}円</td>
      <td>{item.memo}</td>
    </tr>
  ))}
</tbody>

items.map(...)はJavaScriptの式なので、JSXの中で使うために外側を{}で囲んでいます。

map()の中では、そのとき処理している1件分のitemを使って、trを1行作っています。

itemsには2件のデータが入っているため、このtrも2回作られます。

1件目
item.name → "はじめてのWebデザイン本"
↓
1行目のtrを作る

2件目
item.name → "小さなサイドテーブル"
↓
2行目のtrを作る

これで、データが増えても同じtrを手書きで追加する必要がなくなります。

気になるものリストをテーブルに2件表示した画面
気になるものリストがテーブルに2件表示されています。

keyを指定する

map()を使って、2件のデータを一覧表示できました。

ただし、この時点ではまだ1つ問題があります。 ブラウザの開発者ツールでConsoleを確認すると、 keyに関する警告が表示されています。

ブラウザの開発者ツールのConsoleにkeyに関する警告が表示された画面
keyを指定していないため、Consoleに警告が表示されています。

画面には問題なく2件表示されていますが、 Reactでmap()を使って一覧を表示するときは、 繰り返して作る各要素にkeyを指定します。

keyは、Reactが一覧の各要素を 識別するために使う値です。

今回は、それぞれのデータにidが用意されています。 このidを使って、trkeyを追加しましょう。

先ほどのtrを、次のように変更します。

<tr key={item.id}>

1件目ではsample-1、 2件目ではsample-2keyとして使われます。

ファイルを保存すると、先ほど表示されていた keyに関する警告は表示されなくなります。

keyには、 同じ一覧の中で重複せず、データを安定して識別できる値を使うのが基本です。

ReactとJavaScriptを分けて見てみよう

今回登場した内容を、ReactとJavaScriptに分けて整理します。

今回登場したReactとJavaScriptの要素
種類 今回登場したもの
React key、JSXの{}を使った一覧表示
JavaScript 配列、オブジェクト、map()

items配列を作ったり、 map()で1件ずつ処理したりする部分はJavaScriptです。

そのJavaScriptの処理によって作ったJSXをReactで表示し、 各要素を識別するためにkeyを指定しています。

今回のまとめ

  • 複数のオブジェクトをitems配列にまとめた
  • []は配列、{}は1件分のオブジェクトを作るために使う
  • items[0]で配列の1件目を取り出せる
  • map()で配列のデータを1件ずつ処理できる
  • map()を使って同じtrを件数分作った
  • Reactの一覧表示では各要素にkeyを指定する
  • idがある場合は、安定したidkeyに使う

今回の完成コード

今回のApp.jsxの完成コードです。 前回までの画面切り替えを残したまま、 items配列をmap()でテーブル表示します。

src/App.jsx

import { useState } from "react";

export default function App() {
  const items = [
    {
      id: "sample-1",
      name: "はじめてのWebデザイン本",
      category: "本",
      status: "気になる",
      price: 2200,
      memo: "図が多くて読みやすそう",
    },
    {
      id: "sample-2",
      name: "小さなサイドテーブル",
      category: "家具",
      status: "欲しい",
      price: 3500,
      memo: "部屋に置きやすそう",
    },
  ];

  const [screen, setScreen] = useState("list");

  if (screen === "create") {
    return (
      <main className="form-screen">
      <header className="screen-header">
        <h1>気になるものリスト</h1>
        <div className="header-actions">
          <button type="button" className="secondary" onClick={() => setScreen("list")}>
            一覧へ
          </button>
        </div>
        </header>

        <h2 className="screen-title">新規登録画面</h2>
      </main>
    );
  }

  if (screen === "edit") {
    return (
      <main className="form-screen">
      <header className="screen-header">
        <h1>気になるものリスト</h1>
        <div className="header-actions">
          <button type="button" className="secondary" onClick={() => setScreen("list")}>
            一覧へ
          </button>
        </div>
        </header>

        <h2 className="screen-title edit-title">編集画面</h2>
      </main>
    );
  }

  return (
    <main className="list-screen">
      <header className="list-header">
        <h1>気になるものリスト</h1>
        <div className="header-actions">
          <button type="button" onClick={() => setScreen("create")}>
            新規登録
          </button>
          <button type="button" onClick={() => setScreen("edit")}>
            編集
          </button>
        </div>
      </header>

      <h2 className="screen-title">一覧画面</h2>

      <table>
        <thead>
          <tr>
            <th>名前</th>
            <th>カテゴリ</th>
            <th>ステータス</th>
            <th>価格</th>
            <th>メモ</th>
          </tr>
        </thead>
        <tbody>
          {items.map((item) => (
            <tr key={item.id}>
              <td>{item.name}</td>
              <td>{item.category}</td>
              <td>{item.status}</td>
              <td>{item.price}円</td>
              <td>{item.memo}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </main>
  );
}

アプリの完成状況

  • ✅ Reactを動かし、JSXを表示する
  • ✅ Stateで画面を切り替える
  • ✅ 1件のデータを表示する
  • ✅ 複数のデータを一覧表示する
  • ⬜ コンポーネントとpropsを使う
  • ⬜ コンポーネントを別ファイルへ分ける
  • ⬜ 新規登録画面を作る
  • ⬜ 一覧データをStateで管理する
  • ⬜ 編集画面を作る
  • ⬜ データを更新する
  • ⬜ データを削除する
  • ⬜ キーワードで検索する
  • ⬜ カテゴリ・ステータスで絞り込む
  • ⬜ localStorageで保存して完成
スポンサーリンク