- DAY 31:フォーム基礎 前半 ― 「input+value+onChange」でフォームの土台を作る
- フォームの入口:inputタグをReactで使う
- valueとonChange ― 「Reactが入力を支配する」仕組み
- Controlled Component(制御されたコンポーネント)とは何か
- 例題:シンプルな「自己紹介フォーム」を作る
- Controlled Componentの「型」を体に染み込ませる
- 練習用テンプレート:DAY 31 前半版「フォーム基礎コンポーネント」
- DAY 31 前半のまとめ
- DAY 31:フォーム基礎 中盤 ― 「input+value+onChange」を設計目線で理解する
- Controlled Componentを「フォームの標準形」として捉える
- 複数項目フォームをControlled Componentで設計する
- Controlled Componentだからできる「リアルタイムな制御」
- 「input+value+onChange」の設計パターンを言語化する
- 練習用テンプレート:DAY 31 中盤版「ログインフォーム」
- DAY 31 中盤のまとめ
- DAY 31:フォーム基礎 後半 ― 「Controlled Component」を自分の標準フォームにする
- Controlled Componentを「フォームの当たり前」にする
- Controlled Componentだからできる「入力制御」を体験する
- エラー表示と組み合わせて「フォームらしさ」を出す
- 小さなフォームを「送信まで」つなげてみる
- 「input+value+onChange」を自分のフォームテンプレートにする
- DAY 31 後半のまとめ ― 「Controlled Component」をフォームの軸にする
DAY 31:フォーム基礎 前半 ― 「input+value+onChange」でフォームの土台を作る
DAY 31では、Reactにおけるフォームの一番基本となる考え方、 input・value・onChange・Controlled Component(制御されたコンポーネント) を学んでいきます。
ここで身につける感覚は、 この先の「ログインフォーム」「プロフィール編集」「問い合わせフォーム」など、 あらゆるフォームの土台になりますので、じっくり進めていきます。
フォームの入口:inputタグをReactで使う
まずは「ただのinput」を置いてみる
HTMLでは、テキスト入力欄は次のように書きます。
<input type="text" />
Reactでも基本は同じですが、 フォームをしっかり扱うためには「Stateとセット」で考える必要があります。
まずは、何も制御していないシンプルなコンポーネントを見てみます。
function SimpleInput() {
return (
<div>
<h2>フォーム基礎(前半)</h2>
<input type="text" />
</div>
);
}
export default SimpleInput;
JSXこの状態では、ブラウザが入力内容を勝手に管理していて、 React側は「何が入力されているか」を知りません。
ここから一歩進んで、 Reactが入力内容を把握し、コントロールできる状態を作っていきます。
valueとonChange ― 「Reactが入力を支配する」仕組み
Stateとvalueをつなぐ
Reactでフォームを扱うときの基本は、
入力欄の中身をStateで管理する
という考え方です。
まず、入力内容を保存するためのStateを用意します。
import { useState } from "react";
function NameInput() {
const [name, setName] = useState("");
return (
<div>
<h2>フォーム基礎(前半)</h2>
<input type="text" />
</div>
);
}
export default NameInput;
JSX次に、この name を input の value に渡します。
<input type="text" value={name} />
JSXこれで、
- 入力欄の表示内容は、常にState
nameの値になります。
ただし、このままだとユーザーが入力しても値は変わりません。 なぜなら、name を更新していないからです。
onChangeで「入力された瞬間にStateを更新する」
そこで登場するのが onChange です。
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
JSXここで起きていることをステップで説明します。
- ユーザーが入力欄に文字を打つ
onChangeイベントが発生し、(e) => setName(e.target.value)が呼ばれるe.target.valueには「今入力された文字列」が入っているsetName(...)によってStatenameが更新される- Reactが再レンダリングし、
value={name}によって入力欄の表示が新しい値になる
この流れによって、
入力欄の中身は、常にStateと同期した状態
になります。
ここが、Reactフォームの一番重要なポイントです。
Controlled Component(制御されたコンポーネント)とは何か
「Reactが値を完全に管理している入力欄」のこと
今の NameInput コンポーネントは、 Controlled Component(制御されたコンポーネント) の典型例です。
function NameInput() {
const [name, setName] = useState("");
return (
<div>
<h2>フォーム基礎(前半)</h2>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<p>現在の名前:{name}</p>
</div>
);
}
JSX「制御されたコンポーネント」とは、
入力欄の値を、ReactのStateが完全に管理しているコンポーネント
のことです。
具体的には、
valueにStateを渡しているonChangeで入力のたびにStateを更新している
この2つが揃っていると、 その入力欄は「Controlled Component」と呼ばれます。
なぜControlled Componentが重要なのか
Controlled Componentにすると、次のようなメリットがあります。
- 入力内容をいつでもStateから参照できる → 送信ボタンを押したときに、Stateからまとめて値を取り出せる
- 入力値に制限をかけやすい → 例えば「数字だけ許可」「最大文字数を制限」などを、
onChange内で制御できる - バリデーション(入力チェック)をしやすい → 「空文字ならエラー」「メール形式でなければエラー」などをStateと組み合わせて管理できる
- 画面の他の部分と連動させやすい → 入力内容に応じてボタンの有効/無効を切り替えるなどが簡単になる
Reactで本格的なフォームを作るときは、 ほぼ必ずこの「Controlled Component」の考え方が土台になります。
例題:シンプルな「自己紹介フォーム」を作る
名前+自己紹介をControlled Componentで管理する
フォーム基礎の前半では、 シンプルな自己紹介フォームを題材にして、 input・textarea・value・onChange・Controlled Componentをまとめて体験してみます。
import { useState } from "react";
function ProfileFormBasic() {
const [name, setName] = useState("");
const [bio, setBio] = useState("");
const handleSubmit = (e) => {
e.preventDefault(); // ページリロードを防ぐ
alert(`送信された自己紹介\n名前: ${name}\n自己紹介: ${bio}`);
};
return (
<div>
<h2>フォーム基礎(前半)― 自己紹介フォーム</h2>
<form onSubmit={handleSubmit}>
<div>
<label>
名前:
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="名前を入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<label>
自己紹介:
<textarea
value={bio}
onChange={(e) => setBio(e.target.value)}
placeholder="簡単な自己紹介を書いてください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<button type="submit">送信</button>
</div>
</form>
<hr />
<div>
<h3>プレビュー</h3>
<p>名前:{name}</p>
<p>自己紹介:{bio}</p>
</div>
</div>
);
}
export default ProfileFormBasic;
JSXここでのポイントを整理します。
nameとbioは、どちらもStateで管理しています。inputとtextareaのvalueに、それぞれnameとbioを渡しています。onChangeで、入力のたびにStateを更新しています。formのonSubmitで、Stateから値を取り出してアラート表示しています。
このフォーム全体が、 「Controlled Componentの集合」 になっています。
Controlled Componentの「型」を体に染み込ませる
どの入力欄でも使える基本形
フォーム基礎の前半で、 ぜひ自分の中に刻んでほしい「型」があります。
それは、次のような形です。
const [value, setValue] = useState("");
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
JSXこの型は、
- メールアドレス入力欄
- パスワード入力欄
- 検索ボックス
- タイトル入力欄
など、あらゆるテキスト入力でそのまま使えます。
さらに、少し応用するとこうなります。
const [age, setAge] = useState("");
<input
type="number"
value={age}
onChange={(e) => {
const v = e.target.value;
// 数字以外を弾く、最大値を制限するなどのロジックもここに書ける
setAge(v);
}}
/>
JSX重要なポイント:
Controlled Componentの基本形は、 「State+value+onChange」の3点セット。 これをそのまま型として覚えておくと、フォーム作りが一気に楽になります。
練習用テンプレート:DAY 31 前半版「フォーム基礎コンポーネント」
最後に、DAY 31前半の内容をすべて含んだ 練習用テンプレートをまとめます。
import { useState } from "react";
function FormBasicDay31() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
alert(`送信された情報\n名前: ${name}\nメール: ${email}`);
};
return (
<div>
<h2>フォーム基礎(DAY 31 前半)</h2>
<form onSubmit={handleSubmit}>
<div>
<label>
名前:
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="名前を入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<label>
メール:
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="メールアドレスを入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<button type="submit">送信</button>
</div>
</form>
<hr />
<div>
<h3>現在の入力内容</h3>
<p>名前:{name}</p>
<p>メール:{email}</p>
</div>
</div>
);
}
export default FormBasicDay31;
JSXDAY 31 前半のまとめ
DAY 31前半で、自分の中に定着させてほしいのは次の4つです。
- input は、ReactでもHTMLと同じタグですが、 本格的に使うときは必ずStateとセットで考えること。
- value にStateを渡すことで、 「入力欄の中身は常にStateと同期した状態」になること。
- onChange で入力のたびにStateを更新することで、 Reactが入力内容を完全に把握できるようになること。
- Controlled Component は、 「value+onChangeでStateに完全に紐づいた入力欄」のことであり、 すべてのフォームの土台になる考え方であること。
この「State+value+onChange」の型が身につくと、 この先のフォーム設計(バリデーション・複数項目・エラー表示など)が、 ぐっと理解しやすく、実装しやすくなっていきます。
DAY 31:フォーム基礎 中盤 ― 「input+value+onChange」を設計目線で理解する
DAY 31の中盤では、前半で触れた input・value・onChange・Controlled Component を、 「ただ書ける」から一歩進んで、設計目線で理解することを目標にします。
ここで身につけたいのは、
- なぜ value と onChange をセットで書くのか
- Controlled Component にすると何が嬉しいのか
- 複数項目のフォームをどう設計するのか
という、フォーム設計の「考え方」です。
Controlled Componentを「フォームの標準形」として捉える
Reactがフォームを支配するとはどういうことか
前半で作ったシンプルな例を、もう一度振り返ります。
import { useState } from "react";
function NameInput() {
const [name, setName] = useState("");
return (
<div>
<h2>フォーム基礎(中盤)</h2>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<p>現在の名前:{name}</p>
</div>
);
}
export default NameInput;
JSXこのコンポーネントでは、
- 入力欄の中身は
value={name}によってStatenameに完全に紐づいています。 - ユーザーが入力するたびに
onChangeが呼ばれ、setNameでStateが更新されます。
つまり、
「入力欄の値は、ReactのStateが唯一の真実(Single Source of Truth)になっている」
という状態です。
これが Controlled Component の本質です。
Uncontrolled Componentとの違いをイメージする
逆に、value と onChange を使わずに、 ただ <input type="text" /> と書いた場合はどうでしょうか。
この場合、
- 入力内容はブラウザが内部的に管理していて、Reactはその値を直接は知りません。
- 値を取り出したいときは、
refを使ってDOMから読み取る必要があります。
これは Uncontrolled Component(制御されていないコンポーネント) に近い状態です。
中盤では、
「Reactでフォームをしっかり作るなら、基本はControlled Componentを使う」
という方針を、自分の中で決めてしまうのがおすすめです。
複数項目フォームをControlled Componentで設計する
名前+メール+年齢の3項目フォームを考える
中盤では、単一の入力欄ではなく、 複数項目を持つフォームをControlled Componentで設計してみます。
例として、次の3項目を持つフォームを考えます。
- 名前(text)
- メール(email)
- 年齢(number)
まずはStateを用意します。
import { useState } from "react";
function ProfileForm() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [age, setAge] = useState("");
return (
<div>
<h2>フォーム基礎(中盤)― プロフィールフォーム</h2>
{/* ここにフォームを作っていきます */}
</div>
);
}
export default ProfileForm;
JSX次に、それぞれのStateを value と onChange に紐づけます。
<form>
<div>
<label>
名前:
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="名前を入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<label>
メール:
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="メールアドレスを入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<label>
年齢:
<input
type="number"
value={age}
onChange={(e) => setAge(e.target.value)}
placeholder="年齢を入力してください"
/>
</label>
</div>
</form>
JSXここで重要なのは、
- 各入力欄が、それぞれ専用のStateに紐づいていること
- すべての入力欄が「Controlled Component」になっていること
です。
この形が、「複数項目フォームの基本形」になります。
Controlled Componentだからできる「リアルタイムな制御」
入力内容に応じてボタンを有効/無効にする
Controlled Componentの強みは、 入力内容に応じてUIをリアルタイムに制御できることです。
例えば、「名前とメールが両方入力されていないと送信ボタンを押せない」 という仕様を簡単に実現できます。
const isValid = name.trim() !== "" && email.trim() !== "";
<button type="submit" disabled={!isValid}>
送信
</button>
JSXフォーム全体のコードはこうなります。
import { useState } from "react";
function ProfileForm() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [age, setAge] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
alert(`送信された情報\n名前: ${name}\nメール: ${email}\n年齢: ${age}`);
};
const isValid = name.trim() !== "" && email.trim() !== "";
return (
<div>
<h2>フォーム基礎(中盤)― プロフィールフォーム</h2>
<form onSubmit={handleSubmit}>
<div>
<label>
名前:
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="名前を入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<label>
メール:
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="メールアドレスを入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<label>
年齢:
<input
type="number"
value={age}
onChange={(e) => setAge(e.target.value)}
placeholder="年齢を入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<button type="submit" disabled={!isValid}>
送信
</button>
</div>
</form>
<hr />
<div>
<h3>現在の入力内容</h3>
<p>名前:{name}</p>
<p>メール:{email}</p>
<p>年齢:{age}</p>
<p>送信可能か:{isValid ? "はい" : "いいえ"}</p>
</div>
</div>
);
}
export default ProfileForm;
JSXここで起きていることは、
isValidが、Statenameとemailに基づいて計算されているdisabled={!isValid}によって、入力状況に応じてボタンの有効/無効が切り替わる
という流れです。
これが、Controlled Componentの大きなメリットです。
「input+value+onChange」の設計パターンを言語化する
どの入力欄でも通用する考え方
中盤では、次のような「設計パターン」を自分の中に持ってほしいです。
- まずStateを決める
- 「この入力欄は何を表すのか?」を考え、 それに対応するStateを用意します。
const [username, setUsername] = useState(""); - valueにStateを渡すjsx
<input type="text" value={username} />- 入力欄の表示内容は、常にStateに紐づきます。
- onChangeでStateを更新するjsx
<input type="text" value={username} onChange={(e) => setUsername(e.target.value)} />- ユーザーの入力に応じて、Stateが更新されます。
- 必要に応じて制御ロジックを追加するjsx
onChange={(e) => { const v = e.target.value; if (v.length <= 20) { setUsername(v); } }}- 最大文字数を制限するなどのロジックを、
onChange内に書けます。
- 最大文字数を制限するなどのロジックを、
この4ステップが、「Controlled Componentを設計する基本パターン」です。
練習用テンプレート:DAY 31 中盤版「ログインフォーム」
最後に、DAY 31中盤の内容をまとめた シンプルなログインフォームのテンプレートを示します。
import { useState } from "react";
function LoginFormBasic() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
alert(`ログイン試行\nメール: ${email}\nパスワード: ${password}`);
};
const isValid =
email.trim() !== "" &&
password.trim() !== "" &&
password.length >= 6;
return (
<div>
<h2>フォーム基礎(DAY 31 中盤)― ログインフォーム</h2>
<form onSubmit={handleSubmit}>
<div>
<label>
メール:
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="メールアドレスを入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<label>
パスワード:
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="パスワードを入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<button type="submit" disabled={!isValid}>
ログイン
</button>
</div>
</form>
<hr />
<div>
<h3>現在の入力状態</h3>
<p>メール:{email}</p>
<p>パスワード:{password ? "入力済み" : "未入力"}</p>
<p>ログイン可能か:{isValid ? "はい" : "いいえ"}</p>
</div>
</div>
);
}
export default LoginFormBasic;
JSXDAY 31 中盤のまとめ
DAY 31中盤で、自分の中に定着させてほしいのは次のポイントです。
- Controlled Component は、「ReactのStateが唯一の真実として入力値を管理するコンポーネント」であること。
- input+value+onChange の3点セットが、フォーム設計の基本形であること。
- 複数項目フォームでも、各入力欄をそれぞれStateに紐づけることで、 入力内容を完全に把握・制御できること。
- Controlled Componentだからこそ、 「入力内容に応じてボタンを無効化する」「リアルタイムにバリデーションする」 といった高度なフォーム挙動を自然に実装できること。
この設計目線が身につくと、 この先のフォーム・コンポーネント設計(エラー表示、複雑なバリデーション、ネストしたフォームなど)が、 ぐっと理解しやすく、実装しやすくなっていきます。
DAY 31:フォーム基礎 後半 ― 「Controlled Component」を自分の標準フォームにする
DAY 31の後半では、 これまで学んできた input・value・onChange・Controlled Component を、 「なんとなく書ける」から 「自分の標準フォームパターン」 にまで引き上げていきます。
ここで目指すのは、
- どんなフォームでもまずこの形で考えられるようになること
- バリデーションやエラー表示の土台を作れるようになること
- 小さなフォームでも「設計されたフォーム」として扱えるようになること
です。
Controlled Componentを「フォームの当たり前」にする
もう一度、基本形をはっきりさせる
まず、Controlled Componentの基本形を改めて確認します。
import { useState } from "react";
function BasicInput() {
const [value, setValue] = useState("");
return (
<div>
<h2>フォーム基礎(後半)</h2>
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<p>現在の入力:{value}</p>
</div>
);
}
export default BasicInput;
JSXこのコンポーネントでは、
valueにStateを渡しているonChangeで入力のたびにStateを更新している
ので、完全に Controlled Component になっています。
後半では、この形を「特別なもの」ではなく、 「フォームを書くときの当たり前のスタート地点」 として捉えてください。
Controlled Componentだからできる「入力制御」を体験する
例:最大文字数を制限する
Controlled Componentの強みは、 入力された瞬間にロジックを挟めることです。
例えば、「ユーザー名は最大20文字まで」という制限を入れてみます。
import { useState } from "react";
function UsernameInput() {
const [username, setUsername] = useState("");
const handleChange = (e) => {
const v = e.target.value;
if (v.length <= 20) {
setUsername(v);
}
};
return (
<div>
<h2>ユーザー名入力(最大20文字)</h2>
<input
type="text"
value={username}
onChange={handleChange}
placeholder="ユーザー名を入力してください(最大20文字)"
/>
<p>現在のユーザー名:{username}</p>
<p>文字数:{username.length} / 20</p>
</div>
);
}
export default UsernameInput;
JSXここで起きていることは、
- ユーザーが入力するたびに
handleChangeが呼ばれる v.length <= 20のときだけsetUsername(v)している- 21文字目以降はStateが更新されないので、入力欄にも反映されない
という流れです。
ポイント:
Controlled Componentでは、「入力された瞬間にチェックして、通すかどうかを決める」ことができます。 これは、ブラウザ任せのUncontrolledな入力ではやりにくい制御です。
エラー表示と組み合わせて「フォームらしさ」を出す
例:メールアドレスの簡単なチェック
次に、メールアドレス入力欄に簡単なエラー表示をつけてみます。
import { useState } from "react";
function EmailInputWithError() {
const [email, setEmail] = useState("");
const isEmpty = email.trim() === "";
const isInvalidFormat = !isEmpty && !email.includes("@");
return (
<div>
<h2>メール入力(簡易バリデーション)</h2>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="メールアドレスを入力してください"
/>
{isEmpty && <p style={{ color: "red" }}>メールアドレスを入力してください。</p>}
{isInvalidFormat && (
<p style={{ color: "red" }}>メールアドレスの形式が正しくありません。</p>
)}
<p>現在のメール:{email}</p>
</div>
);
}
export default EmailInputWithError;
JSXここでのポイントは、
- 入力値
emailをStateで管理している isEmptyやisInvalidFormatを、Stateに基づいて計算している- 条件に応じてエラーメッセージを表示している
というところです。
重要な感覚:
Controlled Componentでは、「入力値 → 状態判定 →エラー表示」という流れを、 すべてReactの中で完結させることができます。
これが、フォームを「ただの入力欄」から「ちゃんと設計されたUI」に変えていく第一歩です。
小さなフォームを「送信まで」つなげてみる
例:問い合わせフォームのミニ版
DAY 31後半では、 小さな問い合わせフォームを題材に、 input・value・onChange・Controlled Componentを「送信まで」つなげてみます。
import { useState } from "react";
function ContactFormMini() {
const [email, setEmail] = useState("");
const [message, setMessage] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
const trimmedEmail = email.trim();
const trimmedMessage = message.trim();
if (trimmedEmail === "" || trimmedMessage === "") {
alert("メールとメッセージの両方を入力してください。");
return;
}
alert(`問い合わせ送信\nメール: ${trimmedEmail}\nメッセージ: ${trimmedMessage}`);
setEmail("");
setMessage("");
};
const isValid =
email.trim() !== "" &&
message.trim() !== "" &&
message.trim().length >= 10;
return (
<div>
<h2>問い合わせフォーム(ミニ版)</h2>
<form onSubmit={handleSubmit}>
<div>
<label>
メール:
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="メールアドレスを入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<label>
メッセージ:
<textarea
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="10文字以上で入力してください"
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<button type="submit" disabled={!isValid}>
送信
</button>
</div>
</form>
<hr />
<div>
<h3>現在の入力状態</h3>
<p>メール:{email}</p>
<p>メッセージ:{message}</p>
<p>送信可能か:{isValid ? "はい" : "いいえ"}</p>
</div>
</div>
);
}
export default ContactFormMini;
JSXここで起きていることを整理します。
emailとmessageをStateで管理している- どちらも
value+onChangeでControlled Componentになっている isValidをStateに基づいて計算し、ボタンのdisabledに反映しているhandleSubmitでpreventDefault()を呼び、ページリロードを防いでいる- 送信後にStateをリセットして、フォームを初期状態に戻している
ここまで来ると、「Reactでフォームを作る一連の流れ」がほぼ見えています。
「input+value+onChange」を自分のフォームテンプレートにする
どんなフォームでもまずこの形から始める
DAY 31後半のゴールは、 次のようなテンプレートを「自分のフォームの出発点」として持つことです。
import { useState } from "react";
function MyFormTemplate() {
const [field1, setField1] = useState("");
const [field2, setField2] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
// field1, field2 を使って何かする
};
const isValid = field1.trim() !== "" && field2.trim() !== "";
return (
<div>
<h2>フォームテンプレート</h2>
<form onSubmit={handleSubmit}>
<div>
<label>
フィールド1:
<input
type="text"
value={field1}
onChange={(e) => setField1(e.target.value)}
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<label>
フィールド2:
<input
type="text"
value={field2}
onChange={(e) => setField2(e.target.value)}
/>
</label>
</div>
<div style={{ marginTop: "8px" }}>
<button type="submit" disabled={!isValid}>
送信
</button>
</div>
</form>
</div>
);
}
export default MyFormTemplate;
JSXこのテンプレートから、
- フィールド名を変える
- 型(text, email, password, number, textarea)を変える
- バリデーションロジックを追加する
- 送信処理をAPI呼び出しに変える
などをしていけば、 かなり多くのフォームが組み立てられるようになります。
DAY 31 後半のまとめ ― 「Controlled Component」をフォームの軸にする
DAY 31後半で、自分の中にしっかり残してほしいのは次のポイントです。
- input+value+onChange の3点セットが、Reactフォームの基本形であり、 それを使った入力欄が Controlled Component であること。
- Controlled Componentでは、 入力された瞬間にロジックを挟めるため、 最大文字数制限・形式チェック・エラー表示・ボタンの有効/無効などを自然に実装できること。
- 小さなフォームでも、 「Stateで値を管理する → valueで表示する → onChangeで更新する → submitでまとめて扱う」 という流れを意識すると、設計されたフォームになること。
- 自分用のフォームテンプレートとして、
useState+value+onChange+onSubmit+isValidのセットを持っておくと、 どんなフォームでも迷わず書き始められること。
この「Controlled Componentを軸にしたフォーム設計」が身につくと、 この先のフォーム・コンポーネント設計(複雑な入力、ネストしたフォーム、エラー管理、API連携など)が、 ぐっと現実的で、楽しく組み立てられるようになっていきます。

