Reactのカスタムフックでフォーム入力処理を共通化する方法を解説!初心者でも使い回せるフォーム作成術
生徒
「Reactでフォームの入力処理を毎回書くのが面倒なんですけど、簡単にまとめる方法ってありますか?」
先生
「とても良い質問ですね。そんなときに便利なのが『カスタムフック』です。フォームの処理を共通化できますよ。」
生徒
「カスタムフック?初めて聞きました!どうやって使うんですか?」
先生
「では、実際にフォーム入力の処理をカスタムフックで共通化する方法を見ていきましょう!」
1. カスタムフックとは?
まず「カスタムフック」とは、Reactの機能のひとつで、useState や useEffect のような「フック(Hook)」を自分で定義して再利用できる仕組みです。
名前の先頭に必ず use をつけて作成します。
たとえば、フォーム入力処理で useState を使う場合、入力項目が増えると同じようなコードが何度も出てきます。
これを1つの関数にまとめて、どのフォームでも使い回せるようにするのが「カスタムフック」です。
つまり、カスタムフックを使うと「同じロジックを何度も書かなくていい」=「コードの重複を減らせる」ようになります。
2. 通常のフォーム入力処理の例
まずはカスタムフックを使わないフォームの例を見てみましょう。ユーザー名を入力するだけの簡単なフォームです。
import React, { useState } from "react";
function App() {
const [name, setName] = useState("");
const handleChange = (event) => {
setName(event.target.value);
};
return (
<div>
<h1>名前入力フォーム</h1>
<input type="text" value={name} onChange={handleChange} />
<p>入力された名前:{name}</p>
</div>
);
}
export default App;
このようなコードは簡単に見えますが、フォーム項目が5つ、10個と増えていくと、そのたびに useState や onChange を増やす必要があり、とても冗長になります。
3. フォーム処理を共通化できるカスタムフックを作ろう
ここからは、同じ処理を何度も書かないように「カスタムフック」を作ってみましょう。
まずは useFormInput という名前で作成します。
import { useState } from "react";
function useFormInput(initialValue) {
const [value, setValue] = useState(initialValue);
const handleChange = (event) => {
setValue(event.target.value);
};
return {
value,
onChange: handleChange,
};
}
export default useFormInput;
このカスタムフックは、入力値と変更イベントをまとめて管理しています。
value と onChange のペアを返すことで、どんな入力フォームにも簡単に使えるようになります。
4. カスタムフックを使ってフォームをシンプルに書く
それでは、先ほど作成した useFormInput を使って、フォームを書き換えてみましょう。
これで複数の入力欄があっても同じ処理を簡単に共有できます。
import React from "react";
import useFormInput from "./useFormInput";
function App() {
const name = useFormInput("");
const email = useFormInput("");
const handleSubmit = (e) => {
e.preventDefault();
alert(`名前: ${name.value}\nメール: ${email.value}`);
};
return (
<form onSubmit={handleSubmit}>
<h1>ユーザー登録フォーム</h1>
<div>
<label>名前:</label>
<input type="text" {...name} />
</div>
<div>
<label>メール:</label>
<input type="email" {...email} />
</div>
<button type="submit">送信</button>
</form>
);
}
export default App;
{...name} のようにスプレッド構文を使うことで、value と onChange を一度に渡せるのがポイントです。
これにより、1行で入力フォームを構築でき、コードが非常にスッキリします。
5. カスタムフックを使うメリット
カスタムフックを使うことで、フォーム入力の処理をひとつの場所にまとめられるため、保守性(メンテナンスのしやすさ)が大幅に向上します。
- どのフォームでも同じ処理を簡単に再利用できる
- コードの重複をなくして、読みやすくなる
- バグが発生しても修正箇所が少ない
また、Reactのチーム開発でも非常に役立ちます。
チーム全体で同じ useFormInput フックを使えば、入力処理の書き方が統一され、レビューも簡単になります。
6. 応用:複数のフォーム入力をまとめて扱う
さらに一歩進めて、フォーム全体をまとめて管理することも可能です。 オブジェクト形式で複数の入力値を管理するカスタムフックを作ると、大規模なフォームにも対応できます。
import { useState } from "react";
function useForm(initialValues) {
const [values, setValues] = useState(initialValues);
const handleChange = (e) => {
const { name, value } = e.target;
setValues({
...values,
[name]: value,
});
};
return {
values,
handleChange,
};
}
export default useForm;
このようにすることで、フォーム項目を name 属性で識別して、一括で管理できるようになります。
小さなプロジェクトでも、大規模な管理画面でも使える柔軟な設計です。
まとめ
カスタムフックでフォーム処理を整理する考え方
今回の記事では、Reactのカスタムフックを使ってフォーム入力処理を共通化する方法について、基礎から応用まで順を追って解説してきました。フォームはWebアプリケーションにおいて非常に登場回数が多く、ユーザー登録、ログイン、検索、設定画面など、ほとんどの画面で入力処理が必要になります。そのため、同じようなuseStateやonChangeのコードを何度も書いていると、ファイルが増えるにつれて管理が難しくなっていきます。
そこで役立つのがカスタムフックです。カスタムフックは、Reactが用意しているフックの仕組みをそのまま活用しながら、自分専用のロジックを関数として切り出せるのが特徴です。特にフォーム入力のように「値を保持する」「変更を検知する」といった処理は、どの画面でもほぼ同じ流れになるため、共通化との相性がとても良い分野です。
useFormInputで実現できること
記事の中で紹介したuseFormInputのようなカスタムフックを使うことで、入力欄ごとにuseStateを書く必要がなくなり、フォーム側のコードは「どんな入力欄があるか」に集中できるようになります。入力値の管理やイベント処理はフック側に任せることで、コンポーネントの見通しが良くなり、初めてコードを読む人でも理解しやすくなります。
また、スプレッド構文を使って{...name}のように渡せる点も、フォームを簡潔に書ける大きなポイントです。これにより、入力欄が増えてもコード量が極端に増えることはなく、フォーム全体がすっきりした構造を保てます。
フォーム全体を管理する応用パターン
応用例として紹介した「オブジェクトでフォーム全体を管理するカスタムフック」は、入力項目が多い画面で特に効果を発揮します。名前、メール、パスワード、住所など、複数の入力項目を一つのstateでまとめて管理できるため、送信処理や入力チェックとも組み合わせやすくなります。
このような設計にしておくと、後からバリデーション処理を追加したり、入力内容を一括で初期化したりするのも簡単です。小さなサンプルから始めて、徐々に実践的な形へ発展させていくことで、Reactらしいコンポーネント設計が身についていきます。
シンプルな振り返り用サンプル
import React from "react";
import useFormInput from "./useFormInput";
function App() {
const username = useFormInput("");
return (
<div>
<h1>シンプル入力フォーム</h1>
<input type="text" placeholder="名前を入力" {...username} />
<p>入力内容:{username.value}</p>
</div>
);
}
export default App;
このように、カスタムフックを使うことで、フォーム入力の基本的な動きはほとんど毎回同じコードで実現できます。あとは画面ごとに必要な項目を組み合わせるだけなので、開発スピードも自然と向上します。
生徒
「最初はカスタムフックって難しそうだと思っていましたが、フォーム処理をまとめるだけでもすごく便利なんですね。」
先生
「そうですね。まずは今回のように入力処理を共通化するところから始めるのがちょうど良いですよ。」
生徒
「同じようなコードを書かなくてよくなるので、見た目もスッキリしますし、修正もしやすそうです。」
先生
「その感覚が大切です。Reactではロジックを部品として切り出すことで、アプリ全体が整理されていきます。」
生徒
「次はバリデーションや送信処理もカスタムフックにまとめてみたいです!」
先生
「ぜひ挑戦してみてください。フォーム周りを理解できると、React開発が一気に楽しくなりますよ。」