
制御されたコンポーネントの概念
制御されたコンポーネントは、フォーム要素の値がReactの状態(State)によって管理されるコンポーネントです。入力値はuseState
で管理され、value
属性とonChange
イベントハンドラを組み合わせて状態と同期します。このアプローチにより、入力値の検証、変換、送信が容易になります。基本的な例は以下の通りです。
import React, { useState } from 'react';
function Form() {
const [inputValue, setInputValue] = useState('');
return (
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
);
}
このコードでは、inputValue
状態が<input>
要素の値を管理し、onChange
で入力値を更新します。Reactが入力値を制御するため、状態とUIが常に同期します。
ハンズオン:シンプルなフォームの構築
制御されたコンポーネントの基本を理解するため、テキスト入力と送信ボタンを持つフォームを作成します。第1回で作成したプロジェクト(my-react-app)のsrc/App.js
を以下のように編集します。
import React, { useState } from 'react';
import './App.css';
function App() {
const [name, setName] = useState('');
const [message, setMessage] = useState('');
const handleSubmit = () => {
if (name.trim()) {
setMessage(`こんにちは、${name}さん!`);
setName('');
} else {
setMessage('名前を入力してください。');
}
};
return (
<div className="app-container">
<h1>シンプルなフォーム</h1>
<div>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="名前を入力"
/>
<button onClick={handleSubmit}>送信</button>
</div>
<p>{message}</p>
</div>
);
}
export default App;
このコードでは、name
状態で入力値を管理し、handleSubmit
関数で入力値を処理します。入力が空でない場合に挨拶メッセージを表示し、空の場合は警告メッセージを表示します。src/App.css
に以下のスタイルを追加して、フォームを見やすくします。
.app-container {
text-align: center;
padding: 20px;
font-family: Arial, sans-serif;
}
input {
padding: 8px;
margin: 10px;
font-size: 16px;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
開発サーバー(npm start
)が起動している状態で保存すると、ブラウザにフォームが表示されます。名前を入力して「送信」をクリックすると挨拶メッセージが表示され、空で送信すると警告が表示されます。この動作は、制御されたコンポーネントが状態と入力を同期させていることを示しています。
複数の入力フィールドの管理
実際のフォームでは、複数の入力フィールドを扱うことが一般的です。複数の状態を個別に管理する代わりに、オブジェクトを使用して効率的に管理できます。App.js
を以下のように変更し、名前とメールアドレスを扱うフォームを作成します。
import React, { useState } from 'react';
import './App.css';
function App() {
const [formData, setFormData] = useState({
name: '',
email: '',
});
const [message, setMessage] = useState('');
const handleChange = (e) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
};
const handleSubmit = () => {
if (formData.name.trim() && formData.email.trim()) {
setMessage(`こんにちは、${formData.name}さん!メール: ${formData.email}`);
setFormData({ name: '', email: '' });
} else {
setMessage('すべてのフィールドを入力してください。');
}
};
return (
<div className="app-container">
<h1>複数フィールドのフォーム</h1>
<div>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
placeholder="名前を入力"
/>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="メールアドレスを入力"
/>
<button onClick={handleSubmit}>送信</button>
</div>
<p>{message}</p>
</div>
);
}
export default App;
このコードでは、formData
オブジェクトで複数の入力値を管理します。handleChange
関数は、入力フィールドのname
属性を使用して状態を動的に更新します。handleSubmit
は、両方のフィールドが入力されている場合にメッセージを表示し、フォームをリセットします。ブラウザで確認すると、名前とメールアドレスを入力して「送信」をクリックすると、両方の値を含むメッセージが表示されます。
ハンズオン:フォームの拡張
制御されたコンポーネントの柔軟性を体感するため、読者自身でフォームをカスタマイズします。以下の課題を試してください。App.js
を編集し、入力された名前の文字数をリアルタイムで表示する機能を追加します。以下は一例です。
import React, { useState } from 'react';
import './App.css';
function App() {
const [formData, setFormData] = useState({
name: '',
email: '',
});
const [message, setMessage] = useState('');
const handleChange = (e) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
};
const handleSubmit = () => {
if (formData.name.trim() && formData.email.trim()) {
setMessage(`こんにちは、${formData.name}さん!メール: ${formData.email}`);
setFormData({ name: '', email: '' });
} else {
setMessage('すべてのフィールドを入力してください。');
}
};
return (
<div className="app-container">
<h1>カスタムフォーム</h1>
<div>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
placeholder="名前を入力"
/>
<p>名前の文字数: {formData.name.length}</p>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="メールアドレスを入力"
/>
<button onClick={handleSubmit}>送信</button>
</div>
<p>{message}</p>
</div>
);
}
export default App;
このコードでは、名前の入力値の長さをリアルタイムで表示します。ブラウザで確認すると、名前を入力するたびに文字数が更新されます。自分で他の検証(例:メールアドレスの形式チェック)や入力フィールド(例:電話番号)を追加し、制御されたコンポーネントの活用方法を試してください。
次のステップに向けて
本記事では、制御されたコンポーネントを使用してフォームを構築し、ユーザー入力を効率的に管理する方法を学びました。フォームは、ユーザーとの対話を深める重要な要素です。第9回では、React Routerを使用してシングルページアプリケーション(SPA)のナビゲーションを実装する方法を学びます。これにより、複数のページをスムーズに切り替えるアプリケーションを構築できます。