Next.jsで学ぶReact講座(完全初心者向け・30日)演習問題・課題 | 第2章:Reactの基本 – 配列とmap

React Next.js
スポンサーリンク

この課題のねらい

この演習は「配列 × map × React の描画」に慣れるためのものです。
ここがわかると、「APIから取ってきた配列を一覧表示する」といった“実務のド真ん中”が一気にイメージしやすくなります。

やることは 3 つです。

配列を map で JSX に変換してリスト表示する
key を正しく設定して、React に要素を識別させる
配列に項目を追加できる小さな UI を作る

順番にかみ砕いていきます。


必須課題① 配列データをリスト表示

配列をそのままでは表示できない → JSXに変換する

まずは固定の配列を用意して、それを画面にリスト表示してみましょう。

"use client";

const lessons = [
  "Reactの基本",
  "Next.jsのページとルーティング",
  "useStateとイベント処理",
];

export default function LessonListPage() {
  return (
    <main style={{ padding: "24px", fontFamily: "sans-serif" }}>
      <h1>講座リスト</h1>

      <ul style={{ marginTop: "12px" }}>
        {lessons.map((title) => (
          <li key={title}>{title}</li>
        ))}
      </ul>
    </main>
  );
}
TSX

ここで大事なポイントは「lessons.map(...) の部分」です。

lessons.map((title) => ( <li>{title}</li> ))

という書き方で、

配列 lessons の各要素(title)を
<li>...</li> という JSX 要素に“変換”している

イメージです。

React は「配列のまま」では表示できません。
「配列 → JSX の配列」に変換する」のが map の役割です。


必須課題② keyを正しく設定

なぜ key が必要なのか

さっきのコードでは、<li key={title}> と書きました。
この key「この要素を一意に識別するための ID」 です。

React が再レンダリングするとき、

前の配列と今の配列を比べて
どの要素が増えたか/消えたか/並び替わったか

を判断します。そのときの手がかりになるのが key です。

key が適当だと、React が「別の要素」と誤解して、
意図しない再描画が起きたりします。

何を key にすべきか

基本の考え方はこうです。

できるだけ「一意な ID」(数字やUUIDなど)を使う
なければ「絶対に重複しない値」を使う(今回の title のように、重複しないことが前提ならOK)
配列の index(0, 1, 2…)は、“とりあえず表示するだけ”ならありだが、並び替えや削除がある場面では推奨されない

文字列配列の簡単な例なら、こういう書き方もアリです。

{lessons.map((title) => (
  <li key={title}>{title}</li>
))}
TSX

ただ、実務に寄せるなら「ID を持ったオブジェクト配列」に慣れておくと良いです。


オブジェクト配列+key付きのリスト例

実務寄りの形にしてみる

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

"use client";

type Lesson = {
  id: number;
  title: string;
};

const lessons: Lesson[] = [
  { id: 1, title: "Reactの基本" },
  { id: 2, title: "Next.jsのページとルーティング" },
  { id: 3, title: "useStateとイベント処理" },
];

export default function LessonListPage() {
  return (
    <main style={{ padding: "24px", fontFamily: "sans-serif" }}>
      <h1>講座リスト</h1>

      <ul style={{ marginTop: "12px" }}>
        {lessons.map((lesson) => (
          <li key={lesson.id}>{lesson.title}</li>
        ))}
      </ul>
    </main>
  );
}
TSX

ここでのポイントは、

Lesson 型で「1件分のデータの形」を定義
lessons: Lesson[] で「Lesson の配列」として扱う
key={lesson.id} として、「一意な id」を key に使う

という形です。

この形に慣れておくと、API から取ってきた JSON をそのまま扱いやすくなります。


挑戦課題:配列を追加できるUI作成

状態として配列を持ち、setState で増やす

いよいよ「配列+useState」の組み合わせです。
小さな TODO 風の UI を作ってみます。

やりたいことは、

最初はいくつかの講座名が入っている
input に新しい講座名を入れて「追加」ボタンを押すと、リストに増える

という挙動です。

"use client";

import { useState } from "react";

type Lesson = {
  id: number;
  title: string;
};

const initialLessons: Lesson[] = [
  { id: 1, title: "Reactの基本" },
  { id: 2, title: "Next.js入門" },
];

export default function LessonListPage() {
  const [lessons, setLessons] = useState<Lesson[]>(initialLessons);
  const [title, setTitle] = useState("");
  const [nextId, setNextId] = useState(3);

  function handleAdd() {
    const trimmed = title.trim();
    if (!trimmed) return;

    const newLesson: Lesson = {
      id: nextId,
      title: trimmed,
    };

    setLessons([...lessons, newLesson]);
    setNextId(nextId + 1);
    setTitle("");
  }

  return (
    <main style={{ padding: "24px", fontFamily: "sans-serif" }}>
      <h1>講座リスト(追加可能)</h1>

      <div style={{ marginTop: "12px", display: "flex", gap: "8px" }}>
        <input
          type="text"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
          placeholder="講座名を入力"
          style={{ padding: "8px", flex: 1 }}
        />
        <button onClick={handleAdd}>追加</button>
      </div>

      <ul style={{ marginTop: "16px" }}>
        {lessons.map((lesson) => (
          <li key={lesson.id}>{lesson.title}</li>
        ))}
      </ul>
    </main>
  );
}
TSX

重要ポイントを整理します。

const [lessons, setLessons] = useState<Lesson[]>(initialLessons);
配列を state として持っています。中身は Lesson 型の配列。

const [title, setTitle] = useState("");
input の中身(新しい講座名)を state で管理。

const [nextId, setNextId] = useState(3);
新しく追加する Lesson に使う ID を管理。
(実務では UUID やサーバー側の ID を使うことも多いですが、今はカウンタで十分)

handleAdd の中身が一番の肝です。

空文字は追加しない(trim してチェック)
新しい Lesson オブジェクトを作る
setLessons([...lessons, newLesson]); で「元の配列+新しい要素」の新配列をセット
setNextId(nextId + 1); で次回用の ID を更新
setTitle(""); で入力欄をリセット

ここで特に大事なのは、

配列を直接書き換えずに、新しい配列を作って set している
lessons.push(...) ではなく、[...lessons, newLesson] を使う)

というところです。

React の state は「不変(immutable)なもの」として扱うのが基本で、
元の配列を変更するのではなく「新しい配列を作る」のが正しいやり方です。


まとめ:配列とmapでつかんでほしいこと

この課題で本当に押さえてほしいのは、次の感覚です。

配列をそのままでは描画できないので、map で「要素 → JSX」に変換する
key は「要素を一意に識別するためのID」で、基本は id などの一意な値を使う
配列を state で持つときは、setState では常に「新しい配列」を作って渡す([...old, newItem] など)

ここまで分かっていると、

APIから取ってきた一覧データの表示
TODOの追加・削除・編集
通知リストやコメント一覧の表示

など、「配列ベースの UI」をかなりの範囲で自力で組み立てられるようになります。

もし余力があれば、この追加 UI に「削除ボタン」を付けて、

各行に「削除」ボタンを置く
押されたときに、その id 以外の要素だけ残す(filter を使う)

という機能も試してみてください。

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