React 基礎 — コンポーネントと Props
このトピックを修了すると
React でコンポーネントを作成し、Props を使ってデータを渡し、複数のコンポーネントを組み合わせて画面を構成できるようになります。
なぜ React なのか
純粋な HTML と JavaScript でも Web ページを作成できます。しかし、ページが複雑になると問題が発生します。
<!-- 同じカード構造を 10 回繰り返す必要がある場合? -->
<div class="card">
<h3>最初の項目</h3>
<p>説明…</p>
</div>
<div class="card">
<h3>2 番目の項目</h3>
<p>説明…</p>
</div>
<!-- ... 8 回さらに -->HTML をコピー&ペーストすると、デザインを変更するときに 10 か所すべてを修正する必要があります。React はこの問題を コンポーネント で解決します。繰り返される UI のパーツを 1 つの部品として作成し、再利用します。
コンポーネントとは
コンポーネントは、UI を返す関数です。
function Card() {
return (
<div className="card">
<h3>タイトル</h3>
<p>説明です</p>
</div>
);
}これが 1 つのコンポーネントです。HTML のように見えるこの構文は JSX と呼ばれます。JavaScript の中にマークアップを記述できるようにする構文です。JSX はブラウザが直接理解できないため、ビルドプロセス中に通常の JavaScript に変換されます。
コンポーネント名は、必ず 大文字で始める必要があります。小文字で始めると、React は HTML タグとして認識します。
コンポーネントの使用
作成したコンポーネントを、別のコンポーネント内でタグのように記述します。
function App() {
return (
<div>
<Card />
<Card />
<Card />
</div>
);
}<Card /> を 3 回記述すると、同じ UI が 3 回レンダリングされます。デザインを変更したい場合は、Card 関数を 1 つ修正するだけで済みます。
Props — コンポーネントにデータを渡す
これまでの Card は、常に同じ内容を表示します。各カードに異なるデータを表示したい場合は、Props(Properties の略)を使用します。
function Card(props) {
return (
<div className="card">
<h3>{props.title}</h3>
<p>{props.description}</p>
</div>
);
}
function App() {
return (
<div>
<Card title="HTML" description="Web の骨格" />
<Card title="CSS" description="Web の衣服" />
<Card title="JS" description="Web の脳みそ" />
</div>
);
}{props.title} — JSX では、中括弧 {} は「ここに JavaScript の値を入れます」という意味です。Props は、親コンポーネントが子コンポーネントに 一方向 に渡すデータです。
分割代入による Props の取得
props.title、props.description を毎回記述するのは面倒です。実務では、分割代入を使用します。
function Card({ title, description }) {
return (
<div className="card">
<h3>{title}</h3>
<p>{description}</p>
</div>
);
}関数パラメータで { title, description } と直接取得します。意味は同じですが、コードがすっきりします。
Props のさまざまな型
Props には、文字列だけでなく、数値、配列、オブジェクト、関数まで渡すことができます。
function UserProfile({ name, age, hobbies, onFollow }) {
return (
<div>
<h2>{name} ({age}歳)</h2>
<ul>
{hobbies.map((hobby, i) => (
<li key={i}>{hobby}</li>
))}
</ul>
<button onClick={onFollow}>フォロー</button>
</div>
);
}
// 使用
<UserProfile
name="太郎"
age={25}
hobbies={["コーディング", "ゲーム", "読書"]}
onFollow={() => alert("フォロー!")}
/>文字列は引用符で、その他の値は中括弧 {} で囲んで渡します。配列を map() で反復処理してリストをレンダリングするパターンは、React で非常に頻繁に使用されます。
children — 特別な Props
コンポーネントタグの間に記述する内容は、children という特別な Props で渡されます。
function Container({ children }) {
return (
<div className="container">
{children}
</div>
);
}
// 使用
<Container>
<h1>タイトル</h1>
<p>ここに入るすべてのものが children です</p>
</Container>children を活用すると、レイアウトコンポーネントを作成できます。外側の枠は固定し、内部の内容のみを変更するパターンです。
コンポーネント分割の基準
いつコンポーネントを分割する必要がありますか?
- 繰り返し される UI のパーツ → コンポーネントとして抽出
- 独立した機能 単位 → コンポーネントとして分割
- 画面が長くなりすぎた場合 → セクションごとに分割
App
├── Header
├── Main
│ ├── SearchBar
│ └── CardList
│ ├── Card
│ ├── Card
│ └── Card
└── Footerこのようにツリー構造で組み合わせることが、React の主要なアイデアです。
Props のデフォルト値の設定
Props が渡されなかった場合に備えて、デフォルト値を設定できます。
function Badge({ label = "NEW", color = "#3498db" }) {
return (
<span style={{
backgroundColor: color,
color: "white",
padding: "4px 8px",
borderRadius: "4px",
fontSize: "12px",
}}>
{label}
</span>
);
}
// デフォルト値の使用
<Badge /> // "NEW" + 青色
<Badge label="HOT" /> // "HOT" + 青色
<Badge label="SALE" color="red" /> // "SALE" + 赤色デフォルト値を設定しておくと、コンポーネントを使用する側ですべての Props を逐一渡す必要がなくなります。オプションで必要なものだけを指定できます。
JSX で注意すべき点
JSX は HTML に似ていますが、いくつかの重要な違いがあります。
// 1. class の代わりに className
<div className="container"> // ✅
<div class="container"> // ❌ class は JavaScript の予約語
// 2. for の代わりに htmlFor
<label htmlFor="email">メール</label> // ✅
// 3. 必ず 1 つのルート要素で囲む必要がある
function Wrong() {
return (
<h1>タイトル</h1> // ❌ 2 つのルート
<p>内容</p>
);
}
function Right() {
return (
<> // ✅ Fragment で囲む
<h1>タイトル</h1>
<p>内容</p>
</>
);
}
// 4. スタイルはオブジェクトで
<div style={{ backgroundColor: "red", fontSize: "16px" }}>
// camelCase + 文字列値
</div><> と </> は Fragment と呼ばれます。不要な <div> ラッパーなしで複数の要素をグループ化できます。
条件付きレンダリング
Props の値に応じて、異なる UI を表示できます。
function StatusBadge({ isOnline }) {
return (
<span>
{isOnline ? "🟢 オンライン" : "⚪ オフライン"}
</span>
);
}
function Notification({ count }) {
return (
<div>
通知
{count > 0 && <span className="badge">{count}</span>}
</div>
);
}&& 演算子は、左側が true の場合にのみ右側をレンダリングします。三項演算子は、true/false の両方を表示する場合に使用します。これらの 2 つのパターンが、React で条件付きレンダリングのほとんどを処理します。
主要なまとめ
| 概念 | 説明 |
|---|---|
| コンポーネント | UI を返す関数 (大文字で開始) |
| JSX | JavaScript の中にマークアップを記述する構文 |
| Props | 親 → 子の一方向データ伝達 |
| children | タグの間に記述する内容を渡す特別な Props |
| 分割代入 | { title } の形式で Props をきれいに取得 |
| デフォルト値 | { label = "NEW" } の形式で未渡しの処理 |
| Fragment | <>...</> 不要な wrapper div を削除 |
React を最初に学ぶ際に最も重要なことは、「どのようなデータがどこからどこへ流れるか」を理解することです。Props は常に上から下へ流れます。子から親のデータを変更したい場合は、親が「これを呼び出すと、私の状態を変更します」という関数を Props として渡します。これが次に学ぶ 状態 (State) につながります。
→ サイトに適用: DevBench — React Intro