
Reactをセットアップするための環境設定
はじめに React(リアクト)は、Facebook(現Meta)が開発したJavaScriptライブラリで、主にWebアプリケーションの**ユーザーインターフ […]
Reactにおけるイベント処理は、ユーザーインタラクションに対応するための重要な概念です。この章では、特にonClick
を中心としたイベント処理の基本から実践的な使い方まで、初心者向けに詳細に解説します。
Reactのイベント処理は通常のHTMLと似ていますが、いくつかの重要な違いがあります:
onclick
→ onClick
return false
では無効にできず、明示的にpreventDefault
を呼ぶ// HTML
<button onclick="handleClick()">クリック</button>
// React
<button onClick={handleClick}>クリック</button>
function ClickExample() {
const handleClick = () => {
console.log('ボタンがクリックされました!');
};
return <button onClick={handleClick}>クリックしてください</button>;
}
イベントハンドラーには主に3つの定義方法があります。
function ButtonComponent() {
function handleClick() {
console.log('クリックされました');
}
return <button onClick={handleClick}>ボタン</button>;
}
function ButtonComponent() {
const handleClick = () => {
console.log('クリックされました');
};
return <button onClick={handleClick}>ボタン</button>;
}
function ButtonComponent() {
return (
<button onClick={() => console.log('クリックされました')}>
ボタン
</button>
);
}
Reactはイベントハンドラーに合成イベント(SyntheticEvent)オブジェクトを渡します。
function EventObjectExample() {
const handleClick = (event) => {
console.log('イベントタイプ:', event.type); // "click"
console.log('クリック位置:', event.clientX, event.clientY);
console.log('ターゲット要素:', event.target);
};
return <button onClick={handleClick}>位置をログに出力</button>;
}
イベント名 | 説明 | 使用例 |
---|---|---|
onClick | クリック時 | ボタン、リンク |
onChange | 値が変更された時 | 入力欄、セレクトボックス |
onSubmit | フォーム送信時 | フォーム |
onFocus | 要素がフォーカスを得た時 | 入力欄 |
onBlur | 要素がフォーカスを失った時 | 入力欄 |
onMouseEnter | マウスが要素に入った時 | ホバー効果 |
onMouseLeave | マウスが要素から出た時 | ホバー効果 |
onKeyDown | キーが押された時 | キーボード操作 |
onKeyUp | キーが離された時 | キーボード操作 |
function MouseEventExample() {
const handleMouseEnter = () => {
console.log('マウスが要素に入りました');
};
const handleMouseLeave = () => {
console.log('マウスが要素から出ました');
};
return (
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
style={{ padding: '20px', backgroundColor: 'lightblue' }}
>
マウスをここに動かしてみてください
</div>
);
}
function KeyboardEventExample() {
const handleKeyDown = (event) => {
if (event.key === 'Enter') {
console.log('Enterキーが押されました');
}
};
return (
<input
type="text"
onKeyDown={handleKeyDown}
placeholder="Enterキーを押してみてください"
/>
);
}
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
const decrement = () => {
setCount(count - 1);
};
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={increment}>増やす</button>
<button onClick={decrement}>減らす</button>
</div>
);
}
function MultipleButtons() {
const [message, setMessage] = useState('ボタンをクリックしてください');
const showHello = () => {
setMessage('こんにちは!');
};
const showGoodbye = () => {
setMessage('さようなら!');
};
const resetMessage = () => {
setMessage('ボタンをクリックしてください');
};
return (
<div>
<p>{message}</p>
<button onClick={showHello}>挨拶</button>
<button onClick={showGoodbye}>別れ</button>
<button onClick={resetMessage}>リセット</button>
</div>
);
}
handleClick
, handleSubmit
, handleChange
インライン関数は簡潔に書けますが、パフォーマンスに影響する可能性があります。
// 推奨(コンポーネントの再レンダリング時に再作成されない)
function Component() {
const handleClick = () => { /* ... */ };
return <button onClick={handleClick}>ボタン</button>;
}
// 非推奨(再レンダリングごとに新しい関数が作成される)
function Component() {
return <button onClick={() => { /* ... */ }}>ボタン</button>;
}
イベントハンドラーに追加の引数を渡す必要がある場合:
function ItemList() {
const items = ['アイテム1', 'アイテム2', 'アイテム3'];
const handleItemClick = (itemName, event) => {
console.log(`${itemName}がクリックされました`, event);
};
return (
<ul>
{items.map((item) => (
<li key={item}>
<button onClick={(e) => handleItemClick(item, e)}>
{item}
</button>
</li>
))}
</ul>
);
}
ReactでもDOMと同じイベント伝搬モデル(バブリングとキャプチャリング)が適用されます。
function EventBubblingExample() {
const handleParentClick = () => {
console.log('親要素がクリックされました');
};
const handleChildClick = (e) => {
console.log('子要素がクリックされました');
e.stopPropagation(); // 伝搬を停止
};
return (
<div onClick={handleParentClick} style={{ padding: '20px', backgroundColor: 'lightgray' }}>
<button onClick={handleChildClick}>子要素のボタン</button>
</div>
);
}
onClickCapture
のように、イベント名にCapture
を追加するとキャプチャフェーズで処理されます。
function EventCaptureExample() {
const handleParentCapture = () => {
console.log('キャプチャフェーズ: 親要素');
};
const handleChildClick = () => {
console.log('バブリングフェーズ: 子要素');
};
return (
<div onClickCapture={handleParentCapture} style={{ padding: '20px', backgroundColor: 'lightblue' }}>
<button onClick={handleChildClick}>クリック</button>
</div>
);
}
function CustomButton({ onClick, children }) {
return (
<button
onClick={onClick}
style={{
padding: '10px 15px',
backgroundColor: '#4CAF50',
color: 'white',
border: 'none',
borderRadius: '4px'
}}
>
{children}
</button>
);
}
function App() {
const handleButtonClick = () => {
alert('カスタムボタンがクリックされました!');
};
return (
<CustomButton onClick={handleButtonClick}>
クリックしてください
</CustomButton>
);
}
function EnhancedButton({ onClick, children }) {
const handleClick = (event) => {
console.log('ボタンがクリックされました:', event);
if (onClick) {
onClick(event); // 親から渡されたハンドラーを呼び出す
}
};
return <button onClick={handleClick}>{children}</button>;
}
function App() {
const handleParentClick = () => {
console.log('親コンポーネントのハンドラー');
};
return (
<EnhancedButton onClick={handleParentClick}>
拡張ボタン
</EnhancedButton>
);
}
// 誤り(レンダリング時に即時実行される)
<button onClick={handleClick()}>クリック</button>
// 正しい
<button onClick={handleClick}>クリック</button>
// 誤り(eventがundefined)
<button onClick={() => handleClick(event)}>クリック</button>
// 正しい
<button onClick={handleClick}>クリック</button>
// または
<button onClick={(e) => handleClick(e)}>クリック</button>
class MyComponent extends React.Component {
handleClick() {
console.log('クリック'); // thisがundefined
}
// 解決法1: コンストラクタでバインド
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
// 解決法2: アロー関数を使用
handleClick = () => {
console.log('クリック');
}
render() {
return <button onClick={this.handleClick}>クリック</button>;
}
}
const handleClick = (event) => {
console.log('イベント詳細:', event);
console.log('ターゲット:', event.target);
console.log('現在の状態:', this.state); // クラスコンポーネントの場合
};
const handleClick = (event) => {
debugger; // 実行を一時停止
// ...
};
function Tooltip({ text, children }) {
const [isVisible, setIsVisible] = useState(false);
return (
<div style={{ position: 'relative', display: 'inline-block' }}>
<span
onMouseEnter={() => setIsVisible(true)}
onMouseLeave={() => setIsVisible(false)}
>
{children}
</span>
{isVisible && (
<div
style={{
position: 'absolute',
bottom: '100%',
left: '50%',
transform: 'translateX(-50%)',
backgroundColor: 'black',
color: 'white',
padding: '5px',
borderRadius: '4px',
marginBottom: '5px'
}}
>
{text}
</div>
)}
</div>
);
}
// 使用例
<Tooltip text="これはツールチップです">
<button>ホバーしてください</button>
</Tooltip>
function DebounceButton({ onClick, children }) {
const [isDisabled, setIsDisabled] = useState(false);
const handleClick = (event) => {
if (isDisabled) return;
setIsDisabled(true);
onClick(event);
setTimeout(() => {
setIsDisabled(false);
}, 1000); // 1秒間無効化
};
return (
<button onClick={handleClick} disabled={isDisabled}>
{isDisabled ? '処理中...' : children}
</button>
);
}
// 使用例
<DebounceButton onClick={() => console.log('処理開始')}>
クリック
</DebounceButton>
onClick
, onMouseEnter
などonClick={handleClick}
(handleClick()
ではない)stopPropagation()
で伝搬を制御イベント処理はReactアプリケーションにインタラクティビティを追加するための基本技術です。適切に実装することで、ユーザーフレンドリーなUIを作成できます。次に学ぶライフサイクルメソッドやフォーム処理と組み合わせることで、さらに高度なインタラクションを実現できるようになります。