モダンJavaScriptの基礎から始める挫折しないためのReact入門 60日コース | Stateを使いこなす - DAY 21:イベント処理

React 60日で身につけるReact
スポンサーリンク
スポンサーリンク
  1. DAY 21:イベント処理 前半 ― 「クリックで動くReact」を理解する最重要ステップ
  2. onClickとは何かをイメージでつかむ
    1. ボタンに「クリックされたらこれをしてね」と命令する仕組み
  3. イベントハンドラとは何か
    1. 「イベントが起きたときに実行される関数」のこと
  4. 関数を「渡す」ことの意味を深く理解する
    1. onClickに「関数を渡す」とはどういうことか
  5. Arrow Function(アロー関数)をイベント処理の文脈で理解する
    1. Arrow Functionは「短く書ける関数」+「イベント処理で必須の書き方」
    2. 引数を渡すときにArrow Functionが必要になる例
  6. 例題1:クリックで数字が増えるカウンターボタン
    1. Stateとイベント処理を組み合わせた最も基本的なパターン
  7. 例題2:選んだ手を表示するミニじゃんけんUI
    1. 引数付きイベントハンドラとArrow Functionの組み合わせ
  8. DAY 21 前半のまとめ
  9. DAY 21:イベント処理 中盤 ― 「onClick+State」を実用レベルに引き上げる
  10. コンポーネント間で「イベント」を渡すという発想
    1. 親コンポーネントがStateを持ち、子コンポーネントがイベントを“きっかけ”にする
  11. 「関数を渡す」Propsを設計する考え方
    1. 名前の付け方で役割をはっきりさせる
  12. Arrow Functionの「使うべき場面」と「使いすぎ注意の場面」
    1. 引数を渡すときはArrow Functionが必須
    2. 逆に「毎回Arrow Functionを書かなくてもいい」場面
  13. よくあるつまずきポイントを具体例で潰しておく
    1. 間違い例1:onClickで関数を「実行」してしまう
    2. 間違い例2:引数付きイベントハンドラでArrow Functionを忘れる
  14. 練習用テンプレート:複数ボタン+イベントハンドラ+State
    1. 「選んだメニューを表示する」ミニアプリ
  15. DAY 21 中盤のまとめ
  16. DAY 21:イベント処理 後半 ― 「実際に使えるイベント処理」を仕上げる時間です
  17. イベント処理の「ひとつ上の使い方」をイメージする
    1. 単なる「クリックで増える」から「意味のある操作」へ
  18. 例題1:ON/OFFを切り替えるトグルボタン
    1. State+onClick+イベントハンドラ+Arrow Function+条件分岐
    2. このコードで起きていることをステップで追う
    3. ここで使われている重要な要素
  19. 例題2:選択状態をトグルするメニュー
    1. 「選ばれているかどうか」をイベントで切り替える
    2. このコードで起きていることをステップで追う
    3. ここで使われている重要な要素
  20. 「イベント処理の流れ」を頭の中で一本の線にする
    1. クリックから画面更新までの流れを言語化する
  21. 練習用テンプレート:カウンター+ON/OFF制御
    1. このテンプレートで確認できること
  22. DAY 21 後半のまとめ

DAY 21:イベント処理 前半 ― 「クリックで動くReact」を理解する最重要ステップ

DAY 21では、Reactでユーザー操作を扱うためのイベント処理の基礎を集中的に学びます。 ここで理解する内容は、今後のReact開発のほぼすべてで使われ続ける、とても重要な考え方です。

扱うキーワードは次の4つです。

  • onClick
  • イベントハンドラ
  • 関数を渡す
  • Arrow Function(アロー関数)

これらはバラバラの概念ではなく、「ユーザーがボタンを押したら画面が変わる」という一連の流れを支える部品です。 ステップバイステップでつなげて理解していきます。

onClickとは何かをイメージでつかむ

ボタンに「クリックされたらこれをしてね」と命令する仕組み

まず、onClickは「クリックされたときに何をするか」を指定するための仕組みです。 Reactでは、HTMLの onclick="..." のように文字列を書くのではなく、関数を渡す必要があります。

最もシンプルな例から見てみます。

function App() {
  return (
    <button onClick={() => alert("クリックされました!")}>
      クリック
    </button>
  );
}
JSX

ここで起きていることは次の通りです。

  • <button ...> は画面に表示されるボタンです。
  • onClick={...} は「クリックされたときに実行する処理」を指定しています。
  • () => alert("クリックされました!") は「クリックされたらアラートを出す関数」です。

重要なのは、onClickには「関数そのもの」を渡しているという点です。 Reactは「ボタンがクリックされた瞬間」に、その関数を呼び出します。

イベントハンドラとは何か

「イベントが起きたときに実行される関数」のこと

イベントハンドラという言葉は、Reactに限らずよく出てきます。 意味はシンプルで、「イベントが起きたときに実行される関数」のことです。

Reactでは、イベントハンドラを自分で定義して、それをonClickに渡すのが基本的な書き方になります。

function App() {
  const handleClick = () => {
    alert("ボタンが押されました!");
  };

  return (
    <button onClick={handleClick}>
      押す
    </button>
  );
}
JSX

ここでの流れを整理すると、

  1. handleClick というイベントハンドラ関数を定義しています。
  2. onClick={handleClick} として、ボタンにその関数を渡しています。
  3. ユーザーがボタンをクリックすると、Reactが handleClick() を呼び出します。

このように、イベントハンドラは「イベントが起きたときに呼ばれる関数」だと理解しておくと、後のState更新とも自然につながります。

関数を「渡す」ことの意味を深く理解する

onClickに「関数を渡す」とはどういうことか

Reactのイベント処理で最も重要なポイントは、 onClickに「関数を渡す」のであって、「関数を実行する」のではないということです。

次の2つを比べてみてください。

<button onClick={handleClick}>OK</button>
JSX
<button onClick={handleClick()}>OK</button>
JSX

見た目は似ていますが、意味はまったく違います。

  • onClick={handleClick}
    • 「このボタンがクリックされたときに、handleClickという関数を実行してね」とReactに渡している状態です。
    • 実際にクリックされるまで、関数は実行されません。
  • onClick={handleClick()}
    • これは「レンダリング時にhandleClickを実行して、その戻り値をonClickに渡している」状態です。
    • つまり、画面が描画されるタイミングで handleClick() が呼ばれてしまい、クリックとは関係なく実行されてしまいます。

React初心者が最もつまずきやすいのが、この違いです。 onClickには「関数そのもの」を渡す必要があるというルールを、ここでしっかり意識しておくと、後のエラーを大きく減らせます。

Arrow Function(アロー関数)をイベント処理の文脈で理解する

Arrow Functionは「短く書ける関数」+「イベント処理で必須の書き方」

Arrow Function(アロー関数)は、JavaScriptの関数を短く書くための記法です。

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

const handleClick = () => {
  console.log("クリックされました");
};
JSX

Reactのイベント処理では、このArrow Functionがほぼ必須と言っていいほど頻繁に使われます。 理由は主に次の3つです。

  1. 短く書けるので、イベントハンドラをたくさん書いても読みやすい
  2. 引数を渡すときに、onClickの中でArrow Functionを使うのが定番パターン
  3. State更新と組み合わせるときに、Arrow Functionが自然に使える

引数を渡すときにArrow Functionが必要になる例

イベントハンドラに引数を渡したい場面を考えてみます。 例えば、「どのボタンが押されたか」をイベントハンドラに伝えたい場合です。

function App() {
  const handleSelect = (selected) => {
    alert(`${selected} が選ばれました`);
  };

  return (
    <div>
      <button onClick={() => handleSelect("グー")}>グー</button>
      <button onClick={() => handleSelect("チョキ")}>チョキ</button>
      <button onClick={() => handleSelect("パー")}>パー</button>
    </div>
  );
}
JSX

ここで起きていることは次の通りです。

  • handleSelect は、selected という引数を受け取るイベントハンドラです。
  • onClick={() => handleSelect("グー")} は、「クリックされたらhandleSelect(“グー”)を実行する関数」をArrow Functionで定義しています。
  • Arrow Functionを使うことで、「クリックされたときにだけ、引数付きでイベントハンドラを呼び出す」ことができます。

もしここで onClick={handleSelect("グー")} と書いてしまうと、 レンダリング時に handleSelect("グー") が実行されてしまい、クリックとは関係なくアラートが出てしまいます。 このように、引数を渡したいときにはArrow Functionが必須だと理解しておくと、イベント処理の書き方が安定します。

例題1:クリックで数字が増えるカウンターボタン

Stateとイベント処理を組み合わせた最も基本的なパターン

ここからは、実際にStateとイベント処理を組み合わせた例を見ていきます。 まずは「クリックすると数字が1増える」カウンターです。

import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  const handleIncrement = () => {
    setCount((prev) => prev + 1);
  };

  return (
    <div>
      <p>現在の値:{count}</p>
      <button onClick={handleIncrement}>
        +1
      </button>
    </div>
  );
}

export default Counter;
JSX

このコードの中で、DAY 21のキーワードがすべて登場しています。

  • onClick
    • onClick={handleIncrement}
    • ボタンがクリックされたときに、handleIncrement が実行されます。
  • イベントハンドラ
    • const handleIncrement = () => { ... }
    • 「クリックされたときに何をするか」を定義した関数です。
  • 関数を渡す
    • onClick={handleIncrement} は、「関数そのもの」を渡しています。
  • Arrow Function
    • const handleIncrement = () => { ... }
    • イベントハンドラをArrow Functionで定義しています。

さらに、State更新も組み合わさっています。

  • setCount((prev) => prev + 1);
    • 前の値 prev をもとに、1増やした値を新しいStateとして設定しています。
    • これにより、クリックのたびに画面が再レンダリングされ、count の表示が更新されます。

この例は、Reactのイベント処理とState更新の「最小構成」です。 ここをしっかり理解しておくと、より複雑なUIでも同じパターンで考えられるようになります。

例題2:選んだ手を表示するミニじゃんけんUI

引数付きイベントハンドラとArrow Functionの組み合わせ

次に、引数を渡すイベント処理の例として、「選んだ手を表示するミニじゃんけんUI」を作ってみます。

import { useState } from "react";

function HandSelector() {
  const [hand, setHand] = useState("");

  const handleSelect = (selectedHand) => {
    setHand(selectedHand);
  };

  return (
    <div>
      <button onClick={() => handleSelect("グー")}>グー</button>
      <button onClick={() => handleSelect("チョキ")}>チョキ</button>
      <button onClick={() => handleSelect("パー")}>パー</button>

      <p>あなたの手:{hand || "まだ選ばれていません"}</p>
    </div>
  );
}

export default HandSelector;
JSX

ここでのポイントを整理します。

  • handleSelect は、selectedHand という引数を受け取るイベントハンドラです。
  • onClick={() => handleSelect("グー")} のように、Arrow Functionを使って「クリックされたときにだけ、引数付きでイベントハンドラを呼ぶ」ようにしています。
  • setHand(selectedHand); によって、State hand が更新され、画面の表示が変わります。
  • hand || "まだ選ばれていません" によって、初期状態(何も選ばれていない状態)にも意味のある表示をしています。

この例では、

  • onClick
  • イベントハンドラ
  • 関数を渡す
  • Arrow Function

のすべてが、**「ユーザーの選択を画面に反映する」という1つの目的のために組み合わさっています。 Reactのイベント処理は、こうした「ユーザー操作 → 関数 → State更新 → 画面更新」という流れで考えると、非常に整理しやすくなります。

DAY 21 前半のまとめ

DAY 21の前半では、Reactのイベント処理の基礎として、

  • onClickは「クリックされたときに実行する関数を渡すための仕組み」であること
  • イベントハンドラは「イベントが起きたときに実行される関数」であり、自分で定義してonClickに渡すこと
  • onClickには「関数そのもの」を渡し、handleClick() のように実行してしまわないことが重要であること
  • Arrow Functionはイベント処理でほぼ必須であり、特に引数を渡すときに不可欠であること
  • State更新はイベントハンドラの中で行い、「イベント → 関数 → State → 画面更新」という流れで考えること

をステップバイステップで確認しました。

読者のみなさんが、この段階で「クリックすると何かが起きる」「選んだものが画面に反映される」という小さなUIを自分で書けるようになっていると、Reactの世界が一気に広がります。 この基礎は、フォーム入力、リスト操作、モーダル表示、ゲームUIなど、あらゆる場面で繰り返し使われていきます。

次のDAY 21中盤では、イベント処理とStateをさらに組み合わせて、 「入力値を扱う」「条件分岐とイベントを組み合わせる」といった、より実践的なパターンに進んでいきます。


DAY 21:イベント処理 中盤 ― 「onClick+State」を実用レベルに引き上げる

DAY 21の中盤では、前半で学んだ onClick / イベントハンドラ / 関数を渡す / Arrow Function を、もう一段「実用レベル」に引き上げていきます。

ここからは、

  • コンポーネント間でイベントを渡す
  • Propsとして「関数」を渡す
  • Arrow Functionの使いどころを見極める
  • よくあるつまずきポイントを避ける

といった、実務でもそのまま使える考え方を身につけていきます。

コンポーネント間で「イベント」を渡すという発想

親コンポーネントがStateを持ち、子コンポーネントがイベントを“きっかけ”にする

Reactでは、親コンポーネントがStateを持ち、子コンポーネントがイベントをきっかけとして親に知らせるという構造がよく使われます。

例えば、「ボタンコンポーネント」と「カウンターコンポーネント」を分けるケースを考えてみます。

function IncrementButton({ onIncrement }) {
  return (
    <button onClick={onIncrement}>
      +1
    </button>
  );
}
JSX

この IncrementButton は、自分ではStateを持たず、 「クリックされたことを親に知らせるためのイベントハンドラ(onIncrement)」をPropsとして受け取っています。

親コンポーネント側は次のようになります。

import { useState } from "react";

function CounterApp() {
  const [count, setCount] = useState(0);

  const handleIncrement = () => {
    setCount((prev) => prev + 1);
  };

  return (
    <div>
      <p>現在の値:{count}</p>
      <IncrementButton onIncrement={handleIncrement} />
    </div>
  );
}
JSX

ここで起きていることを整理すると、

  • 親コンポーネント CounterAppcount というStateを持っています。
  • 親は handleIncrement というイベントハンドラを定義しています。
  • 親は IncrementButtononIncrement={handleIncrement} として「関数をPropsとして渡して」います。
  • 子コンポーネント IncrementButton は、onClick={onIncrement} として、その関数をボタンのイベントハンドラとして使っています。
  • ユーザーがボタンをクリックすると、onIncrement が呼ばれ、結果として親の handleIncrement が実行されます。

重要ポイント:

  • Propsには「値」だけでなく「関数」も渡せます。
  • 子コンポーネントは「イベントが起きたことを親に知らせるための“入り口”として関数Propsを使う」イメージです。
  • 親がStateを持ち、子がイベントをトリガーする構造は、Reactの王道パターンです。

「関数を渡す」Propsを設計する考え方

名前の付け方で役割をはっきりさせる

関数をPropsとして渡すときは、名前の付け方がとても重要です。 読み手が「何が起きるのか」を直感的に理解できるようにするためです。

よく使われるパターンは次のようなものです。

  • onClick / onChange / onSubmit など、イベント名に on を付ける
  • onIncrement / onSelect / onDelete など、「何が起きるか」を表す動詞を付ける

先ほどの例では、IncrementButton に対して onIncrement というProps名を使いました。

function IncrementButton({ onIncrement }) {
  return (
    <button onClick={onIncrement}>
      +1
    </button>
  );
}
JSX

この名前から、

  • 「このボタンは“増やす”ためのボタンなんだな」
  • 「クリックされたら何かがインクリメントされるんだな」

という意図が読み取れます。

重要ポイント:

  • 関数Propsは「イベントの入り口」なので、onXxx という名前にすると分かりやすくなります。
  • コンポーネントの役割と関数Propsの名前が一致していると、コード全体の見通しが良くなります。

Arrow Functionの「使うべき場面」と「使いすぎ注意の場面」

引数を渡すときはArrow Functionが必須

前半でも触れましたが、イベントハンドラに引数を渡したいときはArrow Functionが必須です。

<button onClick={() => handleSelect("グー")}>グー</button>
JSX

ここでは、

  • () => handleSelect("グー") というArrow FunctionをonClickに渡しています。
  • クリックされたときにだけ handleSelect("グー") が実行されます。

このように、「クリックされたときにだけ、特定の引数を付けて関数を呼びたい」場面では、Arrow Functionが最適です。

逆に「毎回Arrow Functionを書かなくてもいい」場面

一方で、引数が不要なイベントハンドラの場合は、Arrow Functionを使わずに、関数そのものを渡す方が読みやすいことも多いです。

<button onClick={handleIncrement}>+1</button>
JSX

このように書くことで、

  • 「クリックされたらhandleIncrementが実行される」という意図がストレートに伝わります。
  • 無駄なArrow Functionを挟まない分、コードがシンプルになります。

重要ポイント:

  • 引数が必要なとき → onClick={() => handleXxx(arg)}
  • 引数が不要なとき → onClick={handleXxx}

という使い分けを意識すると、コードが自然で読みやすくなります。

よくあるつまずきポイントを具体例で潰しておく

間違い例1:onClickで関数を「実行」してしまう

<button onClick={handleIncrement()}>+1</button>
JSX

これは、レンダリング時に handleIncrement() が実行されてしまい、 クリックとは関係なくStateが更新されてしまいます。

正しくは次のように書きます。

<button onClick={handleIncrement}>+1</button>
JSX

ポイント:

  • onClickには「関数そのもの」を渡す。
  • () を付けると「実行」になってしまうので注意する。

間違い例2:引数付きイベントハンドラでArrow Functionを忘れる

<button onClick={handleSelect("グー")}>グー</button>
JSX

これも同じく、レンダリング時に handleSelect("グー") が実行されてしまいます。 正しくは次のように書きます。

<button onClick={() => handleSelect("グー")}>グー</button>
JSX

ポイント:

  • 引数を渡したいときは、必ずArrow Functionでラップする。
  • 「クリックされたときにだけ実行される関数」をArrow Functionで定義して渡すイメージです。

練習用テンプレート:複数ボタン+イベントハンドラ+State

「選んだメニューを表示する」ミニアプリ

ここまでの内容をまとめて練習できるテンプレートとして、 「選んだメニューを表示する」ミニアプリを示します。

import { useState } from "react";

function MenuButton({ label, onSelect }) {
  return (
    <button onClick={() => onSelect(label)}>
      {label}
    </button>
  );
}

function MenuSelector() {
  const [selectedMenu, setSelectedMenu] = useState("");

  const handleSelectMenu = (menu) => {
    setSelectedMenu(menu);
  };

  const menus = ["ホーム", "プロフィール", "設定"];

  return (
    <div>
      <h2>メニュー選択</h2>

      <div>
        {menus.map((menu) => (
          <MenuButton
            key={menu}
            label={menu}
            onSelect={handleSelectMenu}
          />
        ))}
      </div>

      <p>
        現在選択中:{selectedMenu || "まだ何も選択されていません"}
      </p>
    </div>
  );
}

export default MenuSelector;
JSX

このコードの中には、DAY 21中盤で押さえておきたいポイントがすべて入っています。

  • onClick
    • MenuButton の中で onClick={() => onSelect(label)} として使っています。
  • イベントハンドラ
    • 親コンポーネント MenuSelectorhandleSelectMenu がイベントハンドラです。
  • 関数を渡す
    • 親から子へ onSelect={handleSelectMenu} として関数をPropsとして渡しています。
  • Arrow Function
    • 子コンポーネントで onClick={() => onSelect(label)} として、引数付きでイベントハンドラを呼び出すために使っています。

さらに、

  • 親がStateを持ち、子がイベントをトリガーする構造
  • Propsとして「値」と「関数」を渡す設計
  • 初期状態(何も選択されていない状態)への表示対応

など、Reactの実用的なパターンが自然に含まれています。

DAY 21 中盤のまとめ

DAY 21の中盤では、

  • 親コンポーネントがStateを持ち、子コンポーネントがイベントをきっかけとして親に知らせる構造を理解したこと
  • Propsとして「関数」を渡し、子コンポーネントがその関数をonClickにセットすることで、イベント処理をコンポーネント間でつなげる方法を学んだこと
  • Arrow Functionの「使うべき場面(引数付き)」と「使いすぎなくてよい場面(引数なし)」の違いを整理したこと
  • onClickに関数を「実行」してしまう間違いと、その修正パターンを具体例で確認したこと
  • 練習用テンプレートを通して、複数ボタン+イベントハンドラ+State+Propsの組み合わせを実際のコードとしてイメージできるようになったこと

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

この段階まで来ると、 「ボタンを押したら何かが起きる」「選んだものが画面に反映される」「親子コンポーネントでイベントをやり取りする」といったUIは、ほぼ自由に作れるようになります。

DAY 21後半では、さらにイベント処理と条件分岐・複数Stateを組み合わせて、 より複雑なインタラクションを扱う練習へと進んでいきます。


DAY 21:イベント処理 後半 ― 「実際に使えるイベント処理」を仕上げる時間です

DAY 21の後半では、これまで学んできた onClick / イベントハンドラ / 関数を渡す / Arrow Function を、実際のアプリでそのまま使えるレベルまで仕上げていきます。

ここでのゴールは、

  • 「イベント処理+State+条件分岐」を組み合わせて、
  • ユーザー操作に応じてUIがきちんと変化するミニアプリを、自分で設計・実装できるようになること

です。

イベント処理の「ひとつ上の使い方」をイメージする

単なる「クリックで増える」から「意味のある操作」へ

前半・中盤では、

  • クリックで数字を増やす
  • 選んだ手を表示する

といった、シンプルなイベント処理を扱いました。

後半では、そこから一歩進んで、

  • 「有効/無効」を切り替える
  • 「選択状態」をトグルする
  • 「条件によってボタンの動きを変える」

といった、より実際のUIに近いパターンを扱っていきます。

例題1:ON/OFFを切り替えるトグルボタン

State+onClick+イベントハンドラ+Arrow Function+条件分岐

まずは、「ON/OFF」を切り替えるトグルボタンを作ってみます。

import { useState } from "react";

function ToggleButton() {
  const [isOn, setIsOn] = useState(false);

  const handleToggle = () => {
    setIsOn((prev) => !prev);
  };

  return (
    <div>
      <p>現在の状態:{isOn ? "ON" : "OFF"}</p>
      <button onClick={handleToggle}>
        {isOn ? "OFFにする" : "ONにする"}
      </button>
    </div>
  );
}

export default ToggleButton;
JSX

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

  1. isOn というBooleanのStateを持っています(初期値は false)。
  2. handleToggle というイベントハンドラを定義しています。
    • setIsOn((prev) => !prev); によって、前の値を反転させています。
  3. ボタンの onClick={handleToggle} によって、クリックされたときに handleToggle が実行されます。
  4. isOn ? "ON" : "OFF" という条件分岐で、表示を切り替えています。
  5. ボタンのラベルも isOn に応じて変わります。

ここで使われている重要な要素

  • onClick
    • onClick={handleToggle} でイベントハンドラを渡しています。
  • イベントハンドラ
    • const handleToggle = () => { ... } が「クリックされたときに実行される関数」です。
  • 関数を渡す
    • onClick={handleToggle} は「関数そのもの」を渡しています。
  • Arrow Function
    • イベントハンドラをArrow Functionで定義しています。
    • State更新にもArrow Function((prev) => !prev)を使っています。
  • 条件分岐
    • isOn ? "ON" : "OFF" で表示を切り替えています。

この例は、「イベント処理+State+条件分岐」が自然に組み合わさった、実用的なパターンです。

例題2:選択状態をトグルするメニュー

「選ばれているかどうか」をイベントで切り替える

次に、「選択状態」をトグルするメニューを作ってみます。

import { useState } from "react";

function SelectableItem({ label, isSelected, onToggle }) {
  return (
    <button
      onClick={onToggle}
      style={{
        backgroundColor: isSelected ? "#4caf50" : "#eee",
        color: isSelected ? "#fff" : "#000",
        marginRight: "8px",
      }}
    >
      {label}
    </button>
  );
}

function SelectableMenu() {
  const [selected, setSelected] = useState(null);

  const handleToggleItem = (label) => {
    setSelected((prev) => (prev === label ? null : label));
  };

  const items = ["ホーム", "プロフィール", "設定"];

  return (
    <div>
      <h2>選択可能メニュー</h2>
      <div>
        {items.map((item) => (
          <SelectableItem
            key={item}
            label={item}
            isSelected={selected === item}
            onToggle={() => handleToggleItem(item)}
          />
        ))}
      </div>
      <p>
        現在選択中:
        {selected ?? "何も選択されていません"}
      </p>
    </div>
  );
}

export default SelectableMenu;
JSX

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

  1. 親コンポーネント SelectableMenuselected というStateを持っています。
    • selected には「現在選択されているメニュー名」または null が入ります。
  2. handleToggleItem というイベントハンドラを定義しています。
    • 引数 label は「どのメニューか」を表します。
    • setSelected((prev) => (prev === label ? null : label)); によって、
      • すでに選択されているものをクリックしたら解除(null
      • 別のものをクリックしたら、そのラベルを選択状態にする というトグル動作を実現しています。
  3. 子コンポーネント SelectableItem は、
    • label(表示する文字)
    • isSelected(選択状態かどうか)
    • onToggle(クリックされたときに呼ぶ関数) をPropsとして受け取っています。
  4. onToggle={() => handleToggleItem(item)} によって、
    • クリックされたときにだけ、handleToggleItem(item) が実行されます。
    • Arrow Functionを使って「引数付きイベントハンドラ」を実現しています。
  5. isSelected に応じて、ボタンの背景色や文字色を変えています。

ここで使われている重要な要素

  • onClick
    • 子コンポーネントで onClick={onToggle} として使っています。
  • イベントハンドラ
    • 親コンポーネントの handleToggleItem がイベントハンドラです。
  • 関数を渡す
    • 親から子へ onToggle={() => handleToggleItem(item)} として関数をPropsとして渡しています。
  • Arrow Function
    • onToggle={() => handleToggleItem(item)} で、引数付きイベントハンドラを実現しています。
  • 条件分岐+State
    • selected === item で選択状態を判定し、見た目を変えています。
    • prev === label ? null : label でトグル動作を実現しています。

この例は、「イベント処理+State+条件分岐+コンポーネント分割+関数Props」という、Reactの実務的なパターンが詰まった形になっています。

「イベント処理の流れ」を頭の中で一本の線にする

クリックから画面更新までの流れを言語化する

ここまでの例を通して、 Reactのイベント処理は次のような一本の流れで考えられるようになります。

  1. ユーザーがボタンをクリックする(イベント発生)
  2. onClick に渡されている関数(イベントハンドラ)が呼び出される
  3. イベントハンドラの中で setXxx(...) によってStateが更新される
  4. Stateが変わると、Reactがコンポーネントを再レンダリングする
  5. 新しいStateに基づいて、表示やスタイル、条件分岐の結果が変わる

この流れの中に、

  • onClick
  • イベントハンドラ
  • 関数を渡す
  • Arrow Function
  • State
  • 条件分岐

がすべて自然に組み込まれています。

重要なのは、「イベント処理は単体のテクニックではなく、StateとUI更新の流れの一部だ」と捉えることです。

練習用テンプレート:カウンター+ON/OFF制御

最後に、DAY 21後半の内容をまとめて練習できるテンプレートとして、 「ONのときだけカウントできるカウンター」を示します。

import { useState } from "react";

function CounterWithToggle() {
  const [count, setCount] = useState(0);
  const [isEnabled, setIsEnabled] = useState(true);

  const handleIncrement = () => {
    if (!isEnabled) {
      return;
    }
    setCount((prev) => prev + 1);
  };

  const handleToggleEnable = () => {
    setIsEnabled((prev) => !prev);
  };

  return (
    <div>
      <h2>ONのときだけ増えるカウンター</h2>

      <p>現在の値:{count}</p>
      <p>状態:{isEnabled ? "ON(増やせます)" : "OFF(増やせません)"}</p>

      <button onClick={handleIncrement}>
        +1
      </button>

      <button onClick={handleToggleEnable}>
        {isEnabled ? "OFFにする" : "ONにする"}
      </button>
    </div>
  );
}

export default CounterWithToggle;
JSX

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

  • onClickに「関数そのもの」を渡すパターン(引数なし)
  • イベントハンドラの中で条件分岐を使い、動作を制御するパターン
  • BooleanのState(isEnabled)を使ってUIの動きを変えるパターン
  • Arrow Functionでイベントハンドラを定義し、State更新に使うパターン

このようなミニアプリを自分で書けるようになると、 Reactのイベント処理は「怖いもの」ではなく、「UIを自由に動かすための道具」だと感じられるようになります。

DAY 21 後半のまとめ

DAY 21の後半では、

  • onClick / イベントハンドラ / 関数を渡す / Arrow Function を、 Stateと条件分岐と組み合わせて「意味のあるUI操作」に昇華させたこと
  • 親コンポーネントがStateを持ち、子コンポーネントがイベントをトリガーする構造を、実用的な例で確認したこと
  • 引数付きイベントハンドラにArrow Functionが必須であること、引数なしの場合は関数そのものを渡す方が読みやすいことを整理したこと
  • トグルボタンや選択メニューなど、実際のアプリでよく使うパターンを通して、イベント処理の「流れ」を一本の線として理解できるようになったこと

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

ここまで来ると、 「ボタンを押したら何かが起きる」「選択状態が変わる」「ON/OFFで動作が変わる」といったUIは、ほぼ自由に作れるようになっています。

この先のDAYでは、 入力フォーム、リスト操作、API連携など、より複雑な場面でも、 今日学んだイベント処理の基礎がそのまま土台として生きてきます。

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