配列を一覧表示しよう

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

今回やること

前回は、JavaScriptのitemオブジェクトを使って、 一覧画面に1件分のデータを表示しました。
今回は、複数のデータを配列にまとめ、 map()を使ってテーブルへ一覧表示します。

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

複数の気になるものを一覧画面のテーブルに表示した状態
今回の完成イメージ:複数のデータを一覧表示
スポンサーリンク

1. 複数のデータを配列で用意しよう

前回は、1つのitemオブジェクトを用意しました。
今回は複数のデータを扱うため、複数のオブジェクトを配列にまとめます。

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件目のデータ }
]

2. まずは1件目をテーブルで表示しよう

前回は、1件分のデータをh3pで表示しました。
今回は複数件を一覧として並べるため、HTMLのtableを使います。

まずは、items配列の1件目をテーブルに表示してみましょう。
配列の1件目はitems[0]で取り出せます。

items[0].name

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

これまでは画面を区別しやすくするために、 <h2 className="screen-title">一覧画面</h2> という見出しを表示していました。
今回から一覧の内容をテーブルで表示するため、この「一覧画面」の見出しは削除します。

あわせて、前回の一覧画面にあった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件表示されることを確認しよう

ファイルを保存して、ブラウザを確認してみましょう。
「はじめてのWebデザイン本」がテーブルに1件表示されればOKです。

気になるものリストをテーブルに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()を使います。

3. map()で一覧表示してみよう

tbodyの中を、map()を使った書き方に変更してみましょう。
詳しい仕組みは、実際に一覧表示したあとで整理します。

<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>

ブラウザで2件表示されることを確認しよう

ファイルを保存して、ブラウザを確認してみましょう。
「はじめてのWebデザイン本」と「小さなサイドテーブル」の2件が表示されればOKです。

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

map()の仕組み

map()はJavaScriptの配列メソッドです。
配列の要素を1件ずつ処理して、その結果から新しい配列を作れます。

先ほど使ったコードの中心部分は、次の形です。

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()の中でそのときのitemを使って trを1行ずつ作っています。

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

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

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

{items.map((item) => (
  // JSX
))}

開発者ツールでConsoleを確認しよう

一覧表示の仕組みを確認できたところで、開発者ツールのConsoleも見てみましょう。
この時点では、keyに関する警告が表示されています。

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

画面には問題なく2件表示されていますが、 Reactで一覧を表示するときには、もう1つ必要な設定があります。

keyとは?

Consoleに表示されていた警告は、 繰り返して作った要素にkeyが指定されていないことを知らせるものです。

Reactでmap()を使って一覧を表示するときは、 繰り返して作る各要素にkeyを指定します。

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

今回のデータには、それぞれidが用意されています。
1件目はsample-1、2件目はsample-2です。

keyには、 同じ一覧の中で重複せず、データを安定して識別できる値を使うのが基本です。
そのため、今回はこのidkeyに使います。

4. keyを追加しよう

それでは、先ほどのtrkeyを追加してみましょう。

map()の中のtrを、次のように変更します。

<tr key={item.id}>

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

Consoleでkeyの警告が消えたことを確認しよう

ファイルを保存して、もう一度開発者ツールのConsoleを確認してみましょう。
先ほど表示されていたkeyに関する警告が消えていればOKです。

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

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

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

items配列を作ったり、 map()で1件ずつ処理したりする部分はJavaScriptです。
そのJavaScriptの処理によって作ったJSXをReactで表示し、 各要素を識別するためにkeyを指定しています。

今回のまとめ

  • 複数のオブジェクトをitems配列にまとめた
  • items[0]で配列の1件目を取り出せる
  • map()で配列のデータを1件ずつ処理できる
  • map()を使って同じtrを件数分作った
  • JSXの中でmap()を使うときは{}で囲む
  • 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>

      <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で保存して完成
スポンサーリンク