はじめに
Reactアプリケーションでユーザーの操作に応じて画面を更新する仕組みについて解説します。本記事では、イベント処理とstate管理の基本的な流れを、TypeScriptを使用して説明します。
イベント処理の基本
イベントハンドラの登録方法
Reactでは、JSX内で直接イベントハンドラを指定できます。
interface ButtonProps {
onSave: () => void;
}
const SaveButton: React.FC<ButtonProps> = ({ onSave }) => {
return (
<button className="btn btn-save" onClick={onSave}>
保存
</button>
);
};
Reactがサポートする主なイベント
イベント種別 | 主なイベント | 用途 |
---|---|---|
マウス | onClick, onDoubleClick | クリック操作 |
フォーム | onChange, onSubmit | 入力値の変更 |
ドラッグ | onDragStart, onDrop | ドラッグ&ドロップ |
キーボード | onKeyDown, onKeyUp | キー入力 |
フォーカス | onFocus, onBlur | フォーカス制御 |
StateとEventの連携
基本的な処理フロー
実装例:フォーム入力の管理
interface FormState {
title: string;
description: string;
}
const SurveyForm: React.FC = () => {
const [formData, setFormData] = useState<FormState>({
title: '',
description: ''
});
const handleTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setFormData(prev => ({
...prev,
title: e.target.value
}));
};
return (
<div>
<input
type="text"
value={formData.title}
onChange={handleTitleChange}
placeholder="タイトル"
/>
<p>入力内容: {formData.title}</p>
</div>
);
};
State更新の2つの方法
setStateとreplaceStateの違い
メソッド | 動作 | 使用場面 |
---|---|---|
setState | 既存stateに部分的にマージ | 通常の更新 |
replaceState | state全体を置き換え | 完全なリセット時 |
更新時の注意点
// ❌ 避けるべき書き方
const handleBadUpdate = () => {
state.title = "新しいタイトル"; // 直接変更はNG
};
// ✅ 正しい書き方
const handleGoodUpdate = () => {
setState(prev => ({
...prev,
title: "新しいタイトル"
}));
};
イベントオブジェクトの活用
SyntheticEventとは
ReactはブラウザのネイティブイベントをSyntheticEventでラップし、ブラウザ間の差異を吸収します。
const TextArea: React.FC = () => {
const handleBlur = (event: React.FocusEvent<HTMLTextAreaElement>) => {
console.log('入力値:', event.target.value);
// 必要に応じてネイティブイベントにアクセス
console.log('ネイティブイベント:', event.nativeEvent);
};
return (
<textarea
onBlur={handleBlur}
className="form-control"
/>
);
};
ドラッグ&ドロップの実装例
interface DragState {
isDragging: boolean;
items: string[];
}
const DragDropZone: React.FC = () => {
const [state, setState] = useState<DragState>({
isDragging: false,
items: []
});
const handleDragEnter = () => {
setState(prev => ({ ...prev, isDragging: true }));
};
const handleDrop = (e: React.DragEvent) => {
e.preventDefault();
const data = e.dataTransfer.getData('text');
setState(prev => ({
items: [...prev.items, data],
isDragging: false
}));
};
return (
<div
className={`drop-zone ${state.isDragging ? 'active' : ''}`}
onDragEnter={handleDragEnter}
onDragOver={(e) => e.preventDefault()}
onDrop={handleDrop}
>
ドロップエリア
</div>
);
};
ベストプラクティス
イベント処理実装のチェックリスト
- イベントハンドラは純粋関数として実装する
- stateの直接変更は避ける
- 必要な場合のみevent.preventDefault()を使用
- パフォーマンスを考慮してuseCallbackを活用
- 型安全性のためTypeScriptの型定義を活用
まとめ
Reactのイベント処理とstate管理の基本的な流れは以下のとおりです。
- コンポーネントにイベントハンドラを登録
- イベントハンドラ内でsetStateを呼び出してstateを更新
- stateの変更によりコンポーネントが自動的に再描画
- renderメソッド内でstateを参照してUIを更新
この仕組みを理解することで、ユーザーの操作に応じた動的なUIを構築できます。TypeScriptを使用することで型安全性も確保しながら、保守性の高いコードを実装できます。