React Hook Formはなぜ使う?useStateでフォームを作った場合と比較する
目次
はじめに
Reactでフォームを作るとき、最初は useState を使って実装することが多いと思います。
例えば、名前だけを入力するフォームなら、
const [name, setName] = useState("");
return (
<input
value={name}
onChange={(e) => setName(e.target.value)}
/>
);
これだけで十分です。
しかし、実際のフォームでは、
名前 メールアドレス パスワード 電話番号 住所
のように項目が増えていきます。
さらに、
必須チェック 文字数チェック メールアドレス形式 エラー表示 送信処理
まで必要になると、少しずつ管理するコードが増えていきます。
そこで使われることが多いのが React Hook Form です。
この記事では、useState でフォームを作る場合と比較しながら、React Hook Formを使う理由を整理します。
useStateでもフォームは作れる
まず、名前とメールアドレスを入力するフォームを考えます。
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
console.log({
name,
email,
});
};
入力欄は、
<input
value={name}
onChange={(e) => setName(e.target.value)}
/>
<input
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
のように書けます。
項目が2つ程度なら、特に問題ありません。
ただし、項目が増えると、
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [phone, setPhone] = useState("");
const [address, setAddress] = useState("");
のようにstateも増えていきます。
つまり、
入力項目を追加 ↓ stateを追加 ↓ onChangeを追加
という管理が必要になります。
バリデーションが入るとさらに増える
例えば、
名前は必須 メールアドレスも必須
という条件を追加するとします。
入力値だけではなく、エラーも管理する必要があります。
const [nameError, setNameError] = useState("");
const [emailError, setEmailError] = useState("");
送信時には、
if (!name) {
setNameError("名前を入力してください");
}
if (!email) {
setEmailError("メールアドレスを入力してください");
}
のような処理も必要になります。
もちろん、この方法が間違っているわけではありません。
ただ、フォームが大きくなるにつれて、
入力値 エラー バリデーション onChange 送信処理
を自分で管理する範囲が増えていきます。
React Hook Formを使うとどうなる?
同じようなフォームをReact Hook Formで書くと、次のようになります。
import { useForm } from "react-hook-form";
type FormValues = {
name: string;
email: string;
};
function UserForm() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormValues>();
const onSubmit = (data: FormValues) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
{...register("name", {
required: "名前を入力してください",
})}
/>
{errors.name && (
<p>{errors.name.message}</p>
)}
<input
{...register("email", {
required: "メールアドレスを入力してください",
})}
/>
{errors.email && (
<p>{errors.email.message}</p>
)}
<button type="submit">
送信
</button>
</form>
);
}
useState 版のように、
const [name, setName] = useState("");
const [email, setEmail] = useState("");
と入力項目ごとにstateを用意していません。
代わりに、
register("name")
のように、その入力欄をReact Hook Formへ登録します。
register は何をしているのか
最初にReact Hook Formを触ったとき、
{...register("name")}
が少し分かりにくいと思います。
これは、
この入力欄を nameというフォーム項目として管理する
ためのものです。
例えば、
<input {...register("name")} />
とすると、送信時に、
const onSubmit = (data) => {
console.log(data);
};
へ、
{
name: "田中",
email: "test@example.com"
}
のようなデータが渡されます。
入力値を項目ごとの useState で管理しなくても、フォームとしてまとめて扱えるようになります。
バリデーションもフォームにまとめられる
例えば、名前を必須にするなら、
<input
{...register("name", {
required: "名前を入力してください",
})}
/>
と書けます。
メールアドレスなら、
<input
{...register("email", {
required: "メールアドレスを入力してください",
})}
/>
のように設定できます。
エラーは、
formState.errors
から取得できます。
{errors.email && (
<p>{errors.email.message}</p>
)}
つまり、
入力項目 + バリデーション + エラー
をReact Hook Formの仕組みでまとめて管理できます。
useStateとReact Hook Formの違い
簡単に整理すると、次のようになります。
| 項目 | useState | React Hook Form |
|---|---|---|
| 小さいフォーム | シンプル | 少し準備が必要 |
| 入力値 | 自分でstate管理 | フォームとして管理 |
| バリデーション | 自分で実装 | registerで設定可能 |
| エラー | 自分で管理 | formState.errors |
| 項目が増えた場合 | 管理コードが増えやすい | 整理しやすい |
React Hook Formには、不要な再レンダリングを抑えやすいという特徴もあります。
useState で入力値を管理すると、
入力 ↓ setState ↓ state更新 ↓ 再レンダリング
という流れになります。
React Hook Formは、すべての入力値を useState で管理する必要がないため、項目数の多いフォームでも扱いやすく設計されています。
すべてReact Hook Formにする必要はない
React Hook Formが便利だからといって、
フォームなら全部React Hook Formにするべき
というわけではないと思います。
例えば、
検索ボックス1つだけ
のようなUIなら、useState だけでも十分です。
React Hook Formのメリットが出やすいのは、
入力項目が多い バリデーションが多い エラー表示が必要 フォーム全体の状態を管理したい
といったケースです。
つまり、
小さなフォーム ↓ useStateでも十分 複雑なフォーム ↓ React Hook Formが便利
という使い分けで考えると分かりやすいと思います。
まとめ
Reactのフォームは useState だけでも作れます。
しかし、入力項目が増えてくると、
state onChange バリデーション エラー
など、自分で管理するコードも増えていきます。
React Hook Formを使うことで、
register handleSubmit formState
を中心にフォームを管理できるようになります。
自分の中では、
useState ↓ 入力値を自分で管理する React Hook Form ↓ フォーム全体の管理を任せる
という違いで考えると理解しやすいです。
React Hook Formは、useStateではフォームを作れないから使うのではありません。
フォームが複雑になったとき、入力値やバリデーション、エラーなどの管理を整理しやすくするために使う。
これがReact Hook Formを使う理由だと思います。



















