React event handlingの基本を、実際にコードを書いて動かしながら学びました。この記事では、クリックイベント、入力イベント、イベントオブジェクト、デフォルト動作の防止まで、ハンズオンで確認した内容を整理していきます。
注記: 本記事に掲載しているユーザー名・PC名はダミーに差し替えています。
Contents
参照元
- はじめてのReact入門 - コンポーネント開発からTodoアプリ制作まで
- Chapter 11: イベントハンドリングの基本
得られるもの
React event handlingの基本的な書き方と、TypeScriptでのイベント型定義を他言語経験者の視点で整理した記事です。
- onClickによるクリックイベントの基本
- onChangeによる入力イベントの処理
- イベントオブジェクトの型定義(MouseEvent, KeyboardEvent, FocusEventなど)
- preventDefaultによるデフォルト動作の防止
- document.getElementByIdがReact的にアンチパターンである理由
ハンズオンでの動作確認を通じて、C/C++やC#のイベント処理との対比も交えながら理解を深められる内容になっています。
プロジェクトのフォルダ構成
src/
├── App.css
├── App.tsx
├── assets/
├── ClickExample.tsx
├── EventExample.tsx
├── FormExample.tsx
├── InputExample.tsx
├── index.css
└── main.tsx
前提条件
- Vite + React + TypeScript のプロジェクトが作成済みであること
- Tailwind CSSが設定済みであること
環境構築やTailwind CSSの導入がまだの方は、前回の記事を参照してください。
クリックイベントの基本
まず、最もシンプルなクリックイベントから確認しました。
src/ClickExample.tsx:
const ClickExample = () => {
const showMessage = (message: string) => {
alert(message)
}
const showTime = () => {
const now = new Date()
alert(`現在の時刻: ${now.toLocaleTimeString()}`)
}
return (
<div className="p-8">
<h2 className="text-2xl font-bold mb-6">様々なクリックイベント</h2>
<div className="space-y-4">
<button
onClick={() => showMessage('こんにちは!')}
className="block bg-blue-500 text-white px-6 py-3 rounded-lg hover:bg-blue-600"
>
挨拶メッセージ
</button>
<button
onClick={showTime}
className="block bg-green-500 text-white px-6 py-3 rounded-lg hover:bg-green-600"
>
現在時刻を表示
</button>
</div>
</div>
)
}
export default ClickExample
ポイントは onClick の書き方が2種類ある点です。引数を渡したい場合は onClick={() => showMessage('こんにちは!')} のようにアロー関数でラップし、引数なしなら onClick={showTime} のように関数名を直接指定します。
「挨拶メッセージ」ボタンを押すとalertで「こんにちは!」と表示され、「現在時刻を表示」ボタンを押すと現在の時刻が表示されました。



入力イベントの処理
次に、テキスト入力のイベントを確認しました。
src/InputExample.tsx:
const InputExample = () => {
const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
console.log('入力された値:', event.target.value)
}
const handleSubmit = () => {
const inputElement = document.getElementById('nameInput') as HTMLInputElement
const inputValue = inputElement.value
if (inputValue.trim() === '') {
alert('名前を入力してください')
} else {
alert(`こんにちは、${inputValue}さん!`)
}
}
return (
<div className="p-8">
<h2 className="text-2xl font-bold mb-6">入力イベントの例</h2>
<div className="max-w-md">
<label className="block text-sm font-medium mb-2">
お名前を入力してください
</label>
<input
id="nameInput"
type="text"
onChange={handleInputChange}
placeholder="名前を入力"
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:border-blue-500"
/>
<button
onClick={handleSubmit}
className="mt-4 bg-blue-500 text-white px-6 py-2 rounded-lg hover:bg-blue-600"
>
送信
</button>
</div>
</div>
)
}
export default InputExample
onChange イベントは、入力欄の値が変わるたびに発火します。コンソールで確認すると、1文字入力するたびに handleInputChange が呼ばれ、h → ho → hog → hoge と入力値が出力されるのがわかりました。




イベントの型について
TypeScriptでは、イベントハンドラの引数に型を明示する必要があります。event はstringではなくイベントオブジェクトです。入力イベントの場合は React.ChangeEvent<HTMLInputElement> を指定します。
C#でいうと、WinFormsの TextChanged イベントで sender や EventArgs を受け取るのと同じ感覚です。event.target が「どのHTML要素で発生したか」、.value がその要素の値を示します。
document.getElementByIdはReact的にアンチパターン
上記の handleSubmit では document.getElementById を使ってDOM要素を直接取得していますが、これはReact的にはアンチパターンです。Reactでは、DOM直接操作を避けて状態(state)で管理するのが基本的な設計思想です。
この書き方でも動作はしますが、後のChapter(useState)で学ぶ状態管理を使えば、よりReactらしい書き方に改善できます。今回は教材のイベントハンドリングの学習として、まずこの形で動作を確認しました。
名前未入力で送信すると「名前を入力してください」のバリデーションが動き、「hoge」と入力して送信すると「こんにちは、hogeさん!」と表示されることを確認しました。
イベントオブジェクトの型定義
Reactでは、イベントの種類ごとに異なる型を使い分けます。
src/EventExample.tsx:
const EventExample = () => {
const handleMouseEvent = (event: React.MouseEvent<HTMLDivElement>) => {
console.log('マウスの位置:', event.clientX, event.clientY)
console.log('クリックされた要素:', event.currentTarget.tagName)
}
const handleKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
console.log('押されたキー:', event.key)
if (event.key === 'Enter') {
alert('Enterキーが押されました!')
}
}
const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {
event.target.style.backgroundColor = 'lightyellow'
}
const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {
event.target.style.backgroundColor = 'white'
}
return (
<div className="p-8">
<h2 className="text-2xl font-bold mb-6">イベントオブジェクトの例</h2>
<div className="space-y-4">
<div>
<button
onClick={handleMouseEvent}
className="bg-green-500 text-white px-6 py-3 rounded-lg hover:bg-green-600"
>
クリック位置を表示(コンソールを確認)
</button>
</div>
<div>
<input
type="text"
onKeyDown={handleKeyPress}
placeholder="何か入力してください(Enterキーを試してみて)"
className="w-full max-w-md px-3 py-2 border border-gray-300 rounded-lg"
/>
</div>
<div>
<input
type="text"
onFocus={handleFocus}
onBlur={handleBlur}
placeholder="フォーカス時に背景色が変わります"
className="w-full max-w-md px-3 py-2 border border-gray-300 rounded-lg"
/>
</div>
</div>
</div>
)
}
export default EventExample
イベント型の一覧
パターンは React.○○Event<対象のHTML要素> です。C#の EventHandler<TEventArgs> でイベント種別ごとに MouseEventArgs, KeyEventArgs を使い分けるのと同じ考え方です。
| イベント | 型 |
|---|---|
| onChange | React.ChangeEvent |
| onClick / onMouseMove | React.MouseEvent |
| onKeyDown / onKeyPress | React.KeyboardEvent |
| onFocus / onBlur | React.FocusEvent |
| onSubmit | React.SubmitEvent |
<> の中はイベントが発生するHTML要素に合わせます。<HTMLInputElement>, <HTMLButtonElement>, <HTMLDivElement> など。
target と currentTarget の違い
event.target の型は EventTarget と推論されるため、tagName などのプロパティにアクセスすると型エラーになります。対処法は2つあります。
型アサーションを使う方法:
console.log('クリックされた要素:', (event.target as HTMLElement).tagName)
currentTarget を使う方法:
console.log('クリックされた要素:', event.currentTarget.tagName)
event.target は実際にクリックされた要素(子要素の可能性あり)、event.currentTarget はイベントハンドラが設定された要素自体を指します。
ボタンクリックでコンソールにマウス座標と要素名が表示され、Enterキー押下でalertが表示され、フォーカス時に背景色がlightyellowに変わることを確認しました。




FormEventの非推奨について
ハンズオン中に React.FormEvent を使ったところ、TypeScriptから「非推奨」の警告が出ました。新しいReactの型定義では React.FormEvent の代わりに React.SubmitEvent を使うよう推奨されています。
デフォルト動作の防止(preventDefault)
ブラウザにはフォーム送信時のページリロードやリンククリック時の画面遷移など、デフォルトの動作があります。preventDefault() でこれらを防止できます。
src/FormExample.tsx:
const FormExample = () => {
const handleSubmit = (event: React.SubmitEvent) => {
event.preventDefault()
const formData = new FormData(event.target as HTMLFormElement)
const name = formData.get('name')
const email = formData.get('email')
alert(`フォーム送信処理\n名前: ${name}\nメール: ${email}`)
}
const handleLinkClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault()
alert('リンクのデフォルト動作を防ぎました')
}
return (
<div className="p-8">
<h2 className="text-2xl font-bold mb-6">preventDefault()の例</h2>
<div className="space-y-8">
<div>
<h3 className="text-lg font-semibold mb-4">フォーム送信の例</h3>
<form onSubmit={handleSubmit} className="max-w-md space-y-4">
<div>
<label className="block text-sm font-medium mb-1">名前</label>
<input
name="name"
type="text"
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
/>
</div>
<div>
<label className="block text-sm font-medium mb-1">メールアドレス</label>
<input
name="email"
type="email"
required
className="w-full px-3 py-2 border border-gray-300 rounded-lg"
/>
</div>
<button
type="submit"
className="w-full bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600"
>
送信(ページはリロードされません)
</button>
</form>
</div>
<div>
<h3 className="text-lg font-semibold mb-4">リンクの例</h3>
<a
href="https://example.com"
onClick={handleLinkClick}
className="text-blue-500 underline hover:text-blue-700"
>
このリンクをクリックしても移動しません
</a>
</div>
</div>
</div>
)
}
export default FormExample
フォームに名前とメールアドレスを入力して送信すると、ページがリロードされずにalertで入力内容が表示されました。リンクをクリックしても example.com には遷移せず、alertが表示されることを確認しました。



まとめ
今回は、Reactのイベントハンドリングの基本を一通りハンズオンで確認しました。
振り返ると、ReactのイベントハンドリングはC#のイベント処理と共通する部分が多いことがわかりました。イベントの種類ごとに型が異なる点は EventHandler<TEventArgs> の使い分けと同じ感覚ですし、event.target と event.currentTarget の違いは sender の使い方に似ています。
TypeScriptでの型定義では、React.○○Event<対象のHTML要素> というパターンを覚えておけば対応できます。また、React.FormEvent が非推奨になり React.SubmitEvent を使うようになっている点は、実際にコードを書いて初めて気づけたポイントでした。
document.getElementById によるDOM直接操作はReact的にはアンチパターンであり、次のChapter(useState)で学ぶ状態管理を使うのが正しいアプローチです。
それでは、また別の記事でお会いしましょう。最後まで読んでいただきありがとうございました!
これまでの学習内容
この記事で紹介した内容の他にも学習した内容を記事にしています。是非、ご覧になってみて下さい。
-
-
Vite React TypeScript setupでTodoAppの開発環境を構築する
Vite React TypeScript setup の手順を、実際のハンズオンを通じてステップバイステップで解説します。この記事は、筆者がReact学習の第一歩として環境構築を行った際の体験をもと ...
続きを見る
-
-
React入門:JSX・コンポーネント・Propsを理解する【他言語経験者向け】
Reactの学習を始めて、JSXの書き方、関数コンポーネント、Propsの仕組みまで一通り手を動かしてみました。この記事では、react jsx propsの基本を他言語経験者の視点で整理していきます ...
続きを見る
-
-
React Event Handling入門:クリック・入力・フォームイベントをハンズオンで学ぶ
React event handlingの基本を、実際にコードを書いて動かしながら学びました。この記事では、クリックイベント、入力イベント、イベントオブジェクト、デフォルト動作の防止まで、ハンズオンで ...
続きを見る
-
-
React useState と useEffect を理解する — 状態管理と副作用の基本
React の useState と useEffect は、コンポーネントの状態管理と副作用処理を担う最も重要な Hook です。この記事では、実際にカウンターやタイマーを作りながら、これらの仕組み ...
続きを見る
-
-
React useContextで学ぶ状態共有 — Props drillingからの脱却
Reactでコンポーネントの階層が深くなると、「親から子へ、子から孫へ」とPropsをバケツリレーのように渡し続ける場面に出会います。これが Props drilling と呼ばれる厄介な問題です。u ...
続きを見る