この課題のねらい
この演習は「配列 × 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 を使う)
という機能も試してみてください。
