React レッスン7
イベント処理
クリック、入力、フォーム送信などのイベントを処理しよう
Reactのイベント処理とは?
Reactでは、HTMLのイベント属性と似た方法でイベントを処理しますが、いくつかの違いがあります。
- イベント名はキャメルケース(
onClick、onChange) - 文字列ではなく関数を渡す
- ReactのSyntheticEvent(合成イベント)が使われる
// HTML での書き方
// <button onclick="handleClick()">クリック</button>
// React での書き方
function App() {
const handleClick = () => {
alert("クリックされました!");
};
return (
<button onClick={handleClick}>クリック</button>
);
// 注意: onClick={handleClick()} と書くと
// レンダリング時に即座に実行されてしまう!
// () をつけずに関数自体を渡すこと
}onClick イベント
最も基本的なクリックイベントのパターンを見てみましょう。
import { useState } from "react";
function ClickExamples() {
const [count, setCount] = useState(0);
const [message, setMessage] = useState("");
// パターン1: 直接関数を渡す
const handleIncrement = () => {
setCount(c => c + 1);
};
// パターン2: 引数を渡したい場合はアロー関数で包む
const handleSetMessage = (text) => {
setMessage(text);
};
// パターン3: イベントオブジェクトを使う
const handleButtonClick = (event) => {
console.log("クリックされたボタン:", event.target.textContent);
console.log("座標:", event.clientX, event.clientY);
};
return (
<div>
<p>カウント: {count}</p>
{/* パターン1 */}
<button onClick={handleIncrement}>+1</button>
{/* パターン2: 引数を渡す */}
<button onClick={() => handleSetMessage("こんにちは")}>
挨拶する
</button>
<button onClick={() => handleSetMessage("さようなら")}>
お別れする
</button>
<p>{message}</p>
{/* パターン3: イベントオブジェクト */}
<button onClick={handleButtonClick}>イベント情報を表示</button>
{/* インラインで直接書く */}
<button onClick={() => setCount(0)}>リセット</button>
</div>
);
}onChange イベント(入力の処理)
フォーム入力の変化を検知するのが onChange です。 Reactではフォーム要素を「制御コンポーネント」として扱うのが基本です。
import { useState } from "react";
function FormInputs() {
const [text, setText] = useState("");
const [selected, setSelected] = useState("apple");
const [checked, setChecked] = useState(false);
const [textarea, setTextarea] = useState("");
return (
<div>
{/* テキスト入力 */}
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="テキストを入力"
/>
<p>入力値: {text}({text.length}文字)</p>
{/* セレクトボックス */}
<select value={selected} onChange={(e) => setSelected(e.target.value)}>
<option value="apple">りんご</option>
<option value="banana">バナナ</option>
<option value="orange">みかん</option>
</select>
<p>選択: {selected}</p>
{/* チェックボックス */}
<label>
<input
type="checkbox"
checked={checked}
onChange={(e) => setChecked(e.target.checked)}
/>
同意する
</label>
<p>チェック: {checked ? "ON" : "OFF"}</p>
{/* テキストエリア */}
<textarea
value={textarea}
onChange={(e) => setTextarea(e.target.value)}
rows={3}
placeholder="自由記述..."
/>
</div>
);
}onSubmit イベント(フォーム送信)
フォーム送信時の処理は onSubmit で行います。preventDefault() でページのリロードを防ぎます。
import { useState } from "react";
function ContactForm() {
const [formData, setFormData] = useState({
name: "",
email: "",
message: "",
});
const [submitted, setSubmitted] = useState(false);
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value, // 動的なキーで更新
}));
};
const handleSubmit = (e) => {
e.preventDefault(); // ページのリロードを防ぐ
// バリデーション
if (!formData.name || !formData.email) {
alert("名前とメールは必須です");
return;
}
console.log("送信データ:", formData);
setSubmitted(true);
// フォームをリセット
setFormData({ name: "", email: "", message: "" });
};
if (submitted) {
return <p>送信完了しました!</p>;
}
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="name">名前:</label>
<input
id="name"
name="name"
value={formData.name}
onChange={handleChange}
required
/>
</div>
<div>
<label htmlFor="email">メール:</label>
<input
id="email"
name="email"
type="email"
value={formData.email}
onChange={handleChange}
required
/>
</div>
<div>
<label htmlFor="message">メッセージ:</label>
<textarea
id="message"
name="message"
value={formData.message}
onChange={handleChange}
/>
</div>
<button type="submit">送信</button>
</form>
);
}その他のイベント
Reactではさまざまなイベントを扱えます。よく使うものを紹介します。
function VariousEvents() {
return (
<div>
{/* キーボードイベント */}
<input
onKeyDown={(e) => {
if (e.key === "Enter") {
console.log("Enterが押されました");
}
}}
onKeyUp={(e) => console.log("キーが離された:", e.key)}
placeholder="キーボードイベント"
/>
{/* マウスイベント */}
<div
onMouseEnter={() => console.log("マウスが入った")}
onMouseLeave={() => console.log("マウスが出た")}
onMouseMove={(e) => console.log(e.clientX, e.clientY)}
style={{ padding: "20px", background: "#f0f0f0" }}
>
マウスを乗せてください
</div>
{/* フォーカスイベント */}
<input
onFocus={() => console.log("フォーカスされた")}
onBlur={() => console.log("フォーカスが外れた")}
placeholder="フォーカスイベント"
/>
{/* スクロールイベント */}
<div
onScroll={(e) => {
console.log("スクロール位置:", e.target.scrollTop);
}}
style={{ height: "100px", overflow: "auto" }}
>
<div style={{ height: "300px" }}>スクロールしてね</div>
</div>
{/* ドラッグ&ドロップ */}
<div
draggable
onDragStart={(e) => console.log("ドラッグ開始")}
onDragEnd={(e) => console.log("ドラッグ終了")}
>
ドラッグしてね
</div>
</div>
);
}イベントの伝播(バブリング)
イベントは子要素から親要素へと伝播します。これを止めたい場合はstopPropagation() を使います。
function EventPropagation() {
return (
<div onClick={() => console.log("親がクリックされた")}>
<button
onClick={(e) => {
e.stopPropagation(); // 親への伝播を止める
console.log("ボタンがクリックされた");
}}
>
クリック
</button>
</div>
);
}
// preventDefault: ブラウザのデフォルト動作を防ぐ
function PreventExample() {
return (
<div>
{/* リンクの遷移を防ぐ */}
<a
href="https://example.com"
onClick={(e) => {
e.preventDefault();
console.log("リンクがクリックされましたが遷移しません");
}}
>
クリックしても遷移しない
</a>
{/* フォームの送信を防ぐ */}
<form onSubmit={(e) => {
e.preventDefault();
console.log("フォームの送信をカスタム処理");
}}>
<button type="submit">送信</button>
</form>
</div>
);
}まとめ
- イベント名はキャメルケース(
onClick、onChange) - 関数を渡す(
onClick={handleClick})、呼び出さない - 引数が必要な場合はアロー関数で包む
preventDefault()でデフォルト動作を防ぐstopPropagation()でイベントの伝播を止める- フォームは「制御コンポーネント」パターンで管理する