モダンJavaScriptの基礎から始める挫折しないためのReact入門 60日コース | Stateを使いこなす - DAY 23:mapによるリスト表示

React 60日で身につけるReact
スポンサーリンク
スポンサーリンク
  1. DAY 23:mapによるリスト表示 前半 ― 「配列を画面に変える」Reactの超重要テクニック
  2. map()とは何かをReactの文脈で理解する
    1. 「配列を別の配列に変換する」ための関数です
  3. JSXでの表示とmap()のつながり
    1. 「配列のデータを、画面上のリストに変える」イメージ
  4. オブジェクト配列を使った、現実的なリスト表示
    1. 「ただの数字」から「意味のあるデータ」へ
    2. このコードで起きていることを分解する
  5. keyとは何か、なぜ必要なのか
    1. 「Reactがリストの各要素を識別するためのID」です
    2. なぜkeyが重要なのか
    3. 何をkeyにすべきか
  6. map()+オブジェクト配列+keyをまとめた基本テンプレート
    1. シンプルな「タスク一覧」コンポーネント
    2. このテンプレートで確認できること
  7. DAY 23 前半のまとめ
  8. DAY 23:mapによるリスト表示 中盤 ― 「実用的なリスト」を設計できるようになる
  9. オブジェクト配列を「設計する」という視点を持つ
    1. まずは「何を一覧表示したいか」を言葉で決める
  10. map()で「カード型UI」に変換する
    1. 単なる<li>ではなく「意味のあるコンポーネント」にする
    2. このコードで起きていることをステップで追う
  11. コンポーネント分割で「1件分の表示」を部品化する
    1. 1件分の表示をコンポーネントにするメリット
    2. この分割の意味
  12. keyの「よくある間違い」と「安全な選び方」
    1. よくある間違い:indexをkeyにしてしまう
    2. 安全な選び方:一意なIDを使う
  13. map+条件付きレンダリングの組み合わせ
    1. 「特定の条件を満たすものだけ表示する」パターン
  14. 練習用テンプレート:記事一覧+未公開記事の非表示
  15. DAY 23 中盤のまとめ
  16. DAY 23:mapによるリスト表示 後半 ― 「動くリスト」を自分で作れるところまで仕上げる
  17. オブジェクト配列+mapで「リストの土台」を作る
    1. まずは「静的なリスト」をしっかり押さえる
  18. Stateを使って「リストを更新できるようにする」
    1. 配列をStateとして持つ
  19. 削除ボタンをつけて「クリックでリストが変わる」体験をする
    1. 削除用のイベントハンドラを作る
    2. このコードで起きていることをステップで追う
  20. keyの役割を「動くリスト」でイメージする
    1. なぜkeyがないと困るのか
    2. 一意なIDをkeyにすることで「安全な更新」ができる
  21. コンポーネント分割で「1件分の表示+削除ボタン」を部品化する
    1. 1件分のタスク表示をコンポーネントにする
    2. この分割の意味
  22. 練習用テンプレート:完了状態を切り替えられるタスクリスト
    1. このテンプレートで確認できること
  23. DAY 23 後半のまとめ

DAY 23:mapによるリスト表示 前半 ― 「配列を画面に変える」Reactの超重要テクニック

DAY 23では、React学習の中でも特に重要なテーマである 「mapによるリスト表示」を扱います。 ここを理解できるかどうかで、Reactを「部品レベル」から「アプリレベル」へ進められるかが大きく変わります。

この前半では、次の4つを軸に進めていきます。

  • map()
  • JSXでの表示
  • オブジェクト配列
  • key

どれも単体で覚えるのではなく、 「配列のデータを、画面上のリストに変換する」という1本の流れとしてつなげて理解していきます。

map()とは何かをReactの文脈で理解する

「配列を別の配列に変換する」ための関数です

まず、map() はJavaScriptの配列メソッドで、 「配列の各要素に対して処理を行い、その結果から新しい配列を作る」ためのものです。

基本形は次のようになります。

const numbers = [1, 2, 3];

const doubled = numbers.map((n) => n * 2);
// doubled は [2, 4, 6] になります。
JavaScript

ここで起きていることはシンプルです。

  • numbers の各要素 n に対して n * 2 を実行
  • その結果を集めて、新しい配列 doubled を作る

Reactでは、この「配列を別の形に変換する」力を使って、 「データの配列 → JSXの配列」という変換を行います。

JSXでの表示とmap()のつながり

「配列のデータを、画面上のリストに変える」イメージ

Reactコンポーネントの中で、配列を画面に表示したいとき、 最もよく使われるパターンが次の形です。

function NumberList() {
  const numbers = [1, 2, 3];

  return (
    <ul>
      {numbers.map((n) => (
        <li key={n}>{n}</li>
      ))}
    </ul>
  );
}
JSX

ここで起きていることをステップで追ってみます。

  1. numbers という配列に [1, 2, 3] が入っています。
  2. numbers.map((n) => (...)) で、各要素 n に対して処理を行っています。
  3. (<li key={n}>{n}</li>) というJSXを返しています。
  4. 結果として、map()<li>...</li> の配列を返します。
  5. { ... } の中にその配列を埋め込むことで、<ul> の中に3つの <li> が表示されます。

重要ポイント:

  • map() は「配列の各要素 → JSX」に変換するために使います。
  • Reactは「JSXの配列」をそのままレンダリングできます。
  • つまり、「配列のデータを画面のリストにする」=map()でJSXに変換するということです。

オブジェクト配列を使った、現実的なリスト表示

「ただの数字」から「意味のあるデータ」へ

実際のアプリでは、単なる数字の配列ではなく、 「オブジェクトの配列」を扱うことがほとんどです。

例えば、ユーザー一覧を表示したいとします。

const users = [
  { id: 1, name: "太郎", email: "taro@example.com" },
  { id: 2, name: "花子", email: "hanako@example.com" },
  { id: 3, name: "健", email: "ken@example.com" },
];
JSX

この「オブジェクト配列」を画面に表示するには、 map() を使って各オブジェクトをJSXに変換します。

function UserList() {
  const users = [
    { id: 1, name: "太郎", email: "taro@example.com" },
    { id: 2, name: "花子", email: "hanako@example.com" },
    { id: 3, name: "健", email: "ken@example.com" },
  ];

  return (
    <div>
      <h2>ユーザー一覧</h2>
      <ul>
        {users.map((user) => (
          <li key={user.id}>
            <p>名前:{user.name}</p>
            <p>メール:{user.email}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}
JSX

このコードで起きていることを分解する

  1. users は「ユーザー情報のオブジェクト」が入った配列です。
  2. users.map((user) => (...)) で、各ユーザーオブジェクトを受け取っています。
  3. (<li key={user.id}>...</li>) というJSXを返しています。
  4. user.nameuser.email を使って、オブジェクトの中身を表示しています。
  5. 結果として、ユーザー一覧が画面に表示されます。

重要ポイント:

  • オブジェクト配列は「現実世界のデータ」を表現するための基本形です。
  • map() を使って「オブジェクト → JSX」に変換することで、 データをそのままUIに反映できます。

keyとは何か、なぜ必要なのか

「Reactがリストの各要素を識別するためのID」です

map() を使ったリスト表示では、 ほぼ必ず key という属性を指定する必要があります。

{users.map((user) => (
  <li key={user.id}>
    ...
  </li>
))}
JSX

この key は、 「Reactがリストの各要素を識別するためのID」です。

Reactは、リストが更新されたときに、

  • どの要素が追加されたか
  • どの要素が削除されたか
  • どの要素が並び替えられたか

を判断する必要があります。 そのときに使われるのが key です。

なぜkeyが重要なのか

もし key を適切に指定しないと、次のような問題が起きることがあります。

  • リストの並び替えや削除のときに、意図しない要素が再利用されてしまう
  • 入力フォームやアニメーションなどで、表示が不自然になる

key を正しく指定することで、 Reactは「この要素はこのデータに対応している」と認識でき、 リストの更新を安全に行えるようになります。

何をkeyにすべきか

最も基本的なルールは、

  • 「その要素を一意に識別できる値」をkeyにする

です。

オブジェクト配列なら、よく次のようなフィールドが使われます。

  • id
  • userId
  • productId
  • など、データベースやAPIから渡される一意なID

先ほどの例では、user.idkey に使いました。

<li key={user.id}>
JSX

これは、「ユーザーごとに一意なIDがある」という前提に基づいています。

map()+オブジェクト配列+keyをまとめた基本テンプレート

シンプルな「タスク一覧」コンポーネント

ここまでの内容をまとめて練習できるテンプレートとして、 「タスク一覧」を表示するコンポーネントを示します。

function TaskList() {
  const tasks = [
    { id: 1, title: "Reactの勉強をする", done: false },
    { id: 2, title: "買い物に行く", done: true },
    { id: 3, title: "メールを返信する", done: false },
  ];

  return (
    <div>
      <h2>タスク一覧</h2>
      <ul>
        {tasks.map((task) => (
          <li key={task.id}>
            <span>
              {task.done ? "✅" : "⬜️"} {task.title}
            </span>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TaskList;
JSX

このテンプレートで確認できること

  • map()
    • tasks.map((task) => (...)) で、配列の各要素をJSXに変換しています。
  • JSXでの表示
    • <li>...</li> の中で、task.titletask.done を使って表示を組み立てています。
  • オブジェクト配列
    • tasks は「タスク情報のオブジェクト」が入った配列です。
  • key
    • key={task.id} で、各タスクを一意に識別しています。

このテンプレートは、 「配列のデータを画面のリストにする」というReactの基本パターンを、 コンパクトに体験できる形になっています。

DAY 23 前半のまとめ

DAY 23の前半では、

  • map() が「配列の各要素を別の形に変換する」ための関数であり、Reactでは「配列のデータ → JSX」に変換するために使うこと
  • JSXの中で map() を使うことで、「配列のデータを画面のリストにする」流れを自然に書けること
  • オブジェクト配列が「現実世界のデータ」を表現するための基本形であり、map() でオブジェクトをJSXに変換することで、ユーザー一覧やタスク一覧などを表示できること
  • key が「Reactがリストの各要素を識別するためのID」であり、一意な値(idなど)を指定することが重要であること
  • タスク一覧のテンプレートを通して、map()+オブジェクト配列+JSX+key の組み合わせを具体的なコードとしてイメージできるようになったこと

が大きなポイントになります。

この段階まで来ると、

  • 「配列のデータをそのままUIに反映する」
  • 「オブジェクト配列から意味のあるリストを作る」

というReactの強みを、自分の手で実感できるようになっているはずです。 中盤以降では、このリスト表示にイベント処理やState更新を組み合わせて、 「クリックで状態が変わるリスト」「削除や追加ができるリスト」へと発展させていきます。


DAY 23:mapによるリスト表示 中盤 ― 「実用的なリスト」を設計できるようになる

DAY 23の中盤では、前半で学んだ map() / JSXでの表示 / オブジェクト配列 / key を、もう一歩「実用的なアプリ」に近づけていきます。

ここからのゴールは、

  • 単なる「配列を表示する」から
  • 「意味のあるデータ構造を持ったリストを設計する」へ進むことです。

オブジェクト配列を「設計する」という視点を持つ

まずは「何を一覧表示したいか」を言葉で決める

リスト表示を考えるとき、いきなりコードを書くのではなく、 「何の一覧を表示したいのか」を言葉で決めるところから始めると、mapの使い方がぐっとクリアになります。

例えば、次のような一覧を考えてみます。

  • 書籍一覧
  • 商品一覧
  • 記事一覧
  • タスク一覧

ここでは「記事一覧」を例にします。

記事に必要な情報を日本語で整理すると、

  • タイトル
  • 著者名
  • 公開日
  • 説明文

などが考えられます。 これをオブジェクトとして表現すると、次のようになります。

const articles = [
  {
    id: 1,
    title: "React入門",
    author: "山田",
    publishedAt: "2024-01-01",
    description: "Reactの基本的な考え方を解説します。",
  },
  {
    id: 2,
    title: "JavaScriptの配列操作",
    author: "佐藤",
    publishedAt: "2024-02-10",
    description: "mapやfilterなどの配列メソッドを紹介します。",
  },
];
JSX

重要ポイント:

  • オブジェクト配列は「現実世界の情報」をそのままコードに落とし込んだものです。
  • 何を表示したいかを言葉で整理してから、オブジェクトのプロパティとして設計すると、mapでの表示が自然になります。

map()で「カード型UI」に変換する

単なる<li>ではなく「意味のあるコンポーネント」にする

前半では <li> を使ったシンプルなリストを扱いましたが、 中盤ではもう少し「カード型UI」に近づけてみます。

function ArticleList() {
  const articles = [
    {
      id: 1,
      title: "React入門",
      author: "山田",
      publishedAt: "2024-01-01",
      description: "Reactの基本的な考え方を解説します。",
    },
    {
      id: 2,
      title: "JavaScriptの配列操作",
      author: "佐藤",
      publishedAt: "2024-02-10",
      description: "mapやfilterなどの配列メソッドを紹介します。",
    },
  ];

  return (
    <div>
      <h2>記事一覧</h2>
      {articles.map((article) => (
        <div
          key={article.id}
          style={{
            border: "1px solid #ccc",
            padding: "8px",
            marginBottom: "8px",
          }}
        >
          <h3>{article.title}</h3>
          <p>著者:{article.author}</p>
          <p>公開日:{article.publishedAt}</p>
          <p>{article.description}</p>
        </div>
      ))}
    </div>
  );
}

export default ArticleList;
JSX

このコードで起きていることをステップで追う

  1. articles は「記事情報のオブジェクト」が入った配列です。
  2. articles.map((article) => (...)) で、各記事オブジェクトを受け取っています。
  3. (<div key={article.id}>...</div>) という「カード型UI」のJSXを返しています。
  4. article.titlearticle.author など、オブジェクトのプロパティを使って表示を組み立てています。
  5. 結果として、「記事一覧」がカードとして画面に表示されます。

重要ポイント:

  • mapの中で返すJSXは、<li> に限らず、<div> や独自コンポーネントなど、自由に設計できます。
  • 「1つのオブジェクト → 1つのカードUI」という対応関係を意識すると、リスト表示の設計がしやすくなります。

コンポーネント分割で「1件分の表示」を部品化する

1件分の表示をコンポーネントにするメリット

リスト表示が複雑になってくると、 「1件分の表示」をコンポーネントとして切り出すと、コードが読みやすくなります。

function ArticleCard({ article }) {
  return (
    <div
      style={{
        border: "1px solid #ccc",
        padding: "8px",
        marginBottom: "8px",
      }}
    >
      <h3>{article.title}</h3>
      <p>著者:{article.author}</p>
      <p>公開日:{article.publishedAt}</p>
      <p>{article.description}</p>
    </div>
  );
}

function ArticleList() {
  const articles = [
    {
      id: 1,
      title: "React入門",
      author: "山田",
      publishedAt: "2024-01-01",
      description: "Reactの基本的な考え方を解説します。",
    },
    {
      id: 2,
      title: "JavaScriptの配列操作",
      author: "佐藤",
      publishedAt: "2024-02-10",
      description: "mapやfilterなどの配列メソッドを紹介します。",
    },
  ];

  return (
    <div>
      <h2>記事一覧</h2>
      {articles.map((article) => (
        <ArticleCard key={article.id} article={article} />
      ))}
    </div>
  );
}

export default ArticleList;
JSX

この分割の意味

  • ArticleCard は「記事1件分の表示」を担当するコンポーネントです。
  • ArticleList は「記事配列をmapで回して、ArticleCardを並べる」役割に集中しています。

重要ポイント:

  • mapの中で「JSXそのもの」を返す代わりに、「コンポーネント」を返すことができます。
  • 「1件分の表示」をコンポーネントにすると、
    • 表示ロジックを再利用しやすくなる
    • 条件付き表示やイベント処理を、そのコンポーネントの中に閉じ込めやすくなる

keyの「よくある間違い」と「安全な選び方」

よくある間違い:indexをkeyにしてしまう

mapを使うとき、次のような書き方をしてしまうことがあります。

{articles.map((article, index) => (
  <ArticleCard key={index} article={article} />
))}
JSX

一見動きますが、これは推奨されません

理由は、

  • リストの並び替えや削除・追加が行われたときに、 indexが変わってしまい、Reactが「別の要素」と誤認する可能性があるためです。

特に、

  • 入力フォームを含むリスト
  • アニメーションやトランジションを含むリスト

では、indexをkeyにすると「意図しない再利用」が起きて、 ユーザー体験が崩れることがあります。

安全な選び方:一意なIDを使う

最も安全で基本的な選び方は、

  • 「そのデータを一意に識別できるID」をkeyにする

です。

オブジェクト配列なら、次のようなフィールドがよく使われます。

  • id
  • userId
  • productId
  • articleId

先ほどの例では、article.id をkeyに使いました。

<ArticleCard key={article.id} article={article} />
JSX

重要ポイント:

  • keyは「Reactがリストの各要素を識別するためのID」です。
  • indexではなく、一意なIDを使う習慣をつけると、後々のバグを大きく減らせます。

map+条件付きレンダリングの組み合わせ

「特定の条件を満たすものだけ表示する」パターン

中盤では、mapと条件付きレンダリングを組み合わせたパターンも押さえておきます。

例えば、「完了していないタスクだけ表示する」リストを考えてみます。

function TodoList() {
  const tasks = [
    { id: 1, title: "Reactの勉強をする", done: false },
    { id: 2, title: "買い物に行く", done: true },
    { id: 3, title: "メールを返信する", done: false },
  ];

  return (
    <div>
      <h2>未完了タスク一覧</h2>
      <ul>
        {tasks
          .filter((task) => !task.done)
          .map((task) => (
            <li key={task.id}>{task.title}</li>
          ))}
      </ul>
    </div>
  );
}
JSX

ここでは、

  • filter() で「未完了のタスクだけ」に絞り込み
  • その結果に対して map() でJSXを生成

という流れになっています。

重要ポイント:

  • mapの前にfilterを挟むことで、「表示したいものだけ」をリストにできます。
  • 「配列 → 絞り込み → JSX」という流れは、実務でも非常によく使われるパターンです。

練習用テンプレート:記事一覧+未公開記事の非表示

最後に、DAY 23中盤の内容をまとめた練習用テンプレートを示します。

import { useState } from "react";

function ArticleCard({ article }) {
  return (
    <div
      style={{
        border: "1px solid #ccc",
        padding: "8px",
        marginBottom: "8px",
      }}
    >
      <h3>{article.title}</h3>
      <p>著者:{article.author}</p>
      <p>公開日:{article.publishedAt}</p>
      <p>{article.description}</p>
    </div>
  );
}

function ArticleList() {
  const [articles] = useState([
    {
      id: 1,
      title: "React入門",
      author: "山田",
      publishedAt: "2024-01-01",
      description: "Reactの基本的な考え方を解説します。",
      isPublished: true,
    },
    {
      id: 2,
      title: "JavaScriptの配列操作",
      author: "佐藤",
      publishedAt: "2024-02-10",
      description: "mapやfilterなどの配列メソッドを紹介します。",
      isPublished: true,
    },
    {
      id: 3,
      title: "非公開記事のテスト",
      author: "テストユーザー",
      publishedAt: "2024-03-01",
      description: "これはまだ公開されていない記事です。",
      isPublished: false,
    },
  ]);

  const publishedArticles = articles.filter((article) => article.isPublished);

  return (
    <div>
      <h2>公開済み記事一覧</h2>
      {publishedArticles.map((article) => (
        <ArticleCard key={article.id} article={article} />
      ))}
    </div>
  );
}

export default ArticleList;
JSX

このテンプレートの中には、

  • オブジェクト配列の設計
  • mapによるカード型UIの生成
  • keyに一意なIDを使うパターン
  • filter+mapによる「表示対象の絞り込み」

が自然に含まれています。

DAY 23 中盤のまとめ

DAY 23の中盤では、

  • オブジェクト配列を「何を一覧表示したいか」という視点から設計すること
  • mapの中で返すJSXを「カード型UI」やコンポーネントにすることで、実用的なリスト表示に近づけたこと
  • 1件分の表示をコンポーネントに切り出し、mapでそのコンポーネントを並べるパターンを体験したこと
  • keyの「indexを使うよくある間違い」と、「一意なIDを使う安全な選び方」を整理したこと
  • filter+mapを組み合わせて、「特定の条件を満たすものだけ表示する」リストを作る流れを確認したこと

が大きなポイントになります。

この段階まで来ると、

  • 「配列のデータ構造を設計し、それをUIに変換する」
  • 「意味のあるリストを自分で組み立てる」

というReactの重要な力を、かなり実感できているはずです。 後半では、ここにイベント処理やState更新を組み合わせて、 「クリックで状態が変わるリスト」「削除や追加ができるリスト」へと発展させていきます。


DAY 23:mapによるリスト表示 後半 ― 「動くリスト」を自分で作れるところまで仕上げる

DAY 23の後半では、 map() / JSXでの表示 / オブジェクト配列 / key を「読むだけ」から「動かせる」レベルまで持っていくことを目標にします。

ここでは、次の流れで進めていきます。

  • オブジェクト配列+mapで「リストの土台」を作る
  • Stateを使って「リストを更新できるようにする」
  • keyの重要性を、実際の挙動からイメージする
  • 練習用テンプレートで「削除できるリスト」を完成させる

オブジェクト配列+mapで「リストの土台」を作る

まずは「静的なリスト」をしっかり押さえる

後半でも、最初の一歩はシンプルな「静的なリスト」です。 ここを土台として、その上にStateやイベントを乗せていきます。

function TodoListStatic() {
  const tasks = [
    { id: 1, title: "Reactの勉強をする", done: false },
    { id: 2, title: "買い物に行く", done: true },
    { id: 3, title: "メールを返信する", done: false },
  ];

  return (
    <div>
      <h2>タスク一覧(静的)</h2>
      <ul>
        {tasks.map((task) => (
          <li key={task.id}>
            {task.done ? "✅" : "⬜️"} {task.title}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TodoListStatic;
JSX

ここでは、

  • オブジェクト配列tasks
  • map()tasks.map((task) => (...))
  • JSXでの表示<li>...</li>
  • keykey={task.id}

という基本セットが揃っています。

この「静的なリスト」が、後半のすべての発展形の出発点になります。

Stateを使って「リストを更新できるようにする」

配列をStateとして持つ

次のステップは、 「配列をStateとして持つ」ことです。

import { useState } from "react";

function TodoList() {
  const [tasks, setTasks] = useState([
    { id: 1, title: "Reactの勉強をする", done: false },
    { id: 2, title: "買い物に行く", done: true },
    { id: 3, title: "メールを返信する", done: false },
  ]);

  return (
    <div>
      <h2>タスク一覧</h2>
      <ul>
        {tasks.map((task) => (
          <li key={task.id}>
            {task.done ? "✅" : "⬜️"} {task.title}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TodoList;
JSX

ここでの変化は1つだけです。

  • const tasks = [...]const [tasks, setTasks] = useState([...])

これによって、

  • tasks は「現在のタスク一覧」
  • setTasks は「タスク一覧を更新するための関数」

という意味を持つようになります。

重要ポイント:

  • 「配列をStateにする」ことで、 mapで表示しているリストを、ユーザー操作に応じて変化させることができるようになります。

削除ボタンをつけて「クリックでリストが変わる」体験をする

削除用のイベントハンドラを作る

次に、「タスクを削除できるリスト」を作ってみます。

import { useState } from "react";

function TodoList() {
  const [tasks, setTasks] = useState([
    { id: 1, title: "Reactの勉強をする", done: false },
    { id: 2, title: "買い物に行く", done: true },
    { id: 3, title: "メールを返信する", done: false },
  ]);

  const handleDelete = (id) => {
    setTasks((prevTasks) => prevTasks.filter((task) => task.id !== id));
  };

  return (
    <div>
      <h2>タスク一覧(削除機能付き)</h2>
      <ul>
        {tasks.map((task) => (
          <li key={task.id}>
            {task.done ? "✅" : "⬜️"} {task.title}
            <button
              style={{ marginLeft: "8px" }}
              onClick={() => handleDelete(task.id)}
            >
              削除
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TodoList;
JSX

このコードで起きていることをステップで追う

  1. tasks はStateとして管理されている配列です。
  2. handleDelete は「削除したいタスクのid」を受け取るイベントハンドラです。
    • setTasks((prevTasks) => prevTasks.filter((task) => task.id !== id));
    • これにより、「指定したid以外のタスクだけ」を残した新しい配列を作り、Stateを更新しています。
  3. tasks.map((task) => (...)) の中で、各タスクに対してJSXを生成しています。
  4. 削除ボタンの onClick={() => handleDelete(task.id)} で、
    • クリックされたタスクの idhandleDelete に渡しています。
  5. Stateが更新されると、Reactが再レンダリングし、削除されたタスクが画面から消えます。

重要ポイント:

  • mapで表示しているリストは、「Stateの配列」をそのまま映したものです。
  • Stateの配列を更新すると、mapの結果も変わり、画面のリストが変化します。
  • ここで、「配列+map+State」が1本の流れとしてつながる感覚を持てると、Reactのリスト操作が一気に楽になります。

keyの役割を「動くリスト」でイメージする

なぜkeyがないと困るのか

削除機能付きのリストを考えると、 key の重要性がよりはっきり見えてきます。

Reactは、リストが変化したときに、

  • どの要素が消えたか
  • どの要素が残っているか

を判断する必要があります。

そのときに使われるのが key です。

もし key を適切に指定していないと、

  • 削除したつもりの要素とは別の要素が再利用されてしまう
  • 入力フォームやチェックボックスの状態が、意図しない形で残ってしまう

といった問題が起きる可能性があります。

一意なIDをkeyにすることで「安全な更新」ができる

先ほどの例では、task.idkey に使いました。

<li key={task.id}>
JSX

これは、

  • 「このJSX要素は、このidのタスクに対応している」

とReactに伝えるためのものです。

削除や追加が行われても、

  • id が変わらない限り、そのタスクに対応する要素は正しく認識されます。

重要ポイント:

  • 動くリスト(削除・追加・並び替えなど)では、key の正しさが特に重要になります。
  • 一意なIDをkeyにすることで、Reactは「どの要素がどのデータに対応しているか」を正しく追跡できます。

コンポーネント分割で「1件分の表示+削除ボタン」を部品化する

1件分のタスク表示をコンポーネントにする

リストが少し複雑になってきたら、 「1件分の表示」をコンポーネントに切り出すと、コードが整理されます。

function TaskItem({ task, onDelete }) {
  return (
    <li>
      {task.done ? "✅" : "⬜️"} {task.title}
      <button
        style={{ marginLeft: "8px" }}
        onClick={() => onDelete(task.id)}
      >
        削除
      </button>
    </li>
  );
}

import { useState } from "react";

function TodoList() {
  const [tasks, setTasks] = useState([
    { id: 1, title: "Reactの勉強をする", done: false },
    { id: 2, title: "買い物に行く", done: true },
    { id: 3, title: "メールを返信する", done: false },
  ]);

  const handleDelete = (id) => {
    setTasks((prevTasks) => prevTasks.filter((task) => task.id !== id));
  };

  return (
    <div>
      <h2>タスク一覧(削除機能付き)</h2>
      <ul>
        {tasks.map((task) => (
          <TaskItem key={task.id} task={task} onDelete={handleDelete} />
        ))}
      </ul>
    </div>
  );
}

export default TodoList;
JSX

この分割の意味

  • TaskItem は「タスク1件分の表示+削除ボタン」を担当します。
  • TodoList は「タスク配列をStateとして管理し、mapでTaskItemを並べる」役割に集中します。

重要ポイント:

  • mapの中で返すものは「JSXそのもの」でも「コンポーネント」でも構いません。
  • 1件分の表示をコンポーネントにすると、
    • 表示ロジックを再利用しやすくなる
    • 条件付き表示やイベント処理を、そのコンポーネントの中に閉じ込めやすくなる

練習用テンプレート:完了状態を切り替えられるタスクリスト

最後に、DAY 23後半の内容をまとめた練習用テンプレートとして、 「完了状態を切り替えられるタスクリスト」を示します。

import { useState } from "react";

function TaskItem({ task, onToggleDone, onDelete }) {
  return (
    <li>
      <button onClick={() => onToggleDone(task.id)}>
        {task.done ? "✅" : "⬜️"}
      </button>
      <span style={{ marginLeft: "8px", marginRight: "8px" }}>
        {task.title}
      </span>
      <button onClick={() => onDelete(task.id)}>削除</button>
    </li>
  );
}

function TodoList() {
  const [tasks, setTasks] = useState([
    { id: 1, title: "Reactの勉強をする", done: false },
    { id: 2, title: "買い物に行く", done: true },
    { id: 3, title: "メールを返信する", done: false },
  ]);

  const handleToggleDone = (id) => {
    setTasks((prevTasks) =>
      prevTasks.map((task) =>
        task.id === id ? { ...task, done: !task.done } : task
      )
    );
  };

  const handleDelete = (id) => {
    setTasks((prevTasks) => prevTasks.filter((task) => task.id !== id));
  };

  return (
    <div>
      <h2>タスク一覧(完了切り替え+削除)</h2>
      <ul>
        {tasks.map((task) => (
          <TaskItem
            key={task.id}
            task={task}
            onToggleDone={handleToggleDone}
            onDelete={handleDelete}
          />
        ))}
      </ul>
    </div>
  );
}

export default TodoList;
JSX

このテンプレートで確認できること

  • map()
    • tasks.map((task) => (...)) で、配列の各要素をコンポーネントに変換しています。
  • JSXでの表示
    • TaskItem コンポーネントの中で、ボタンやテキストを組み合わせて表示しています。
  • オブジェクト配列
    • tasks は「タスク情報のオブジェクト」が入った配列です。
  • key
    • key={task.id} で、各タスクを一意に識別しています。
  • State+map+イベント処理
    • handleToggleDone で完了状態をトグル
    • handleDelete でタスクを削除
    • どちらも「配列を新しい形に変換してStateを更新する」ことで、画面のリストを変化させています。

DAY 23 後半のまとめ

DAY 23の後半では、

  • 「静的なリスト」から始めて、配列をStateとして持つことで「動くリスト」に発展させたこと
  • mapで表示しているリストが、Stateの配列と1対1で対応していることを、削除機能を通して体感したこと
  • keyが「Reactがリストの各要素を識別するためのID」であり、動くリストでは特に重要になることを確認したこと
  • 1件分の表示をコンポーネントに分割し、mapでそのコンポーネントを並べるパターンを使って、コードの見通しを良くしたこと
  • 完了状態の切り替え+削除ができるタスクリストのテンプレートを通して、 「オブジェクト配列+map+JSX+key+State+イベント処理」が1本の流れとしてつながる感覚を掴んだこと

が大きなポイントになります。

ここまで来ると、

  • 「配列のデータ構造を設計し、それをUIに変換し、さらにユーザー操作で更新する」

というReactの中核的な力を、自分の手で扱えるようになっているはずです。

タイトルとURLをコピーしました