Reactでフォームを実装する際に、ユーザーが入力項目を追加したり削除したりできる動的フォームを作成することは、特にアンケートや申請フォーム、タスク管理などのアプリケーションで役立ちます。この記事では、Reactを使って動的フォームを実装する方法を詳しく説明し、簡単なコード例も紹介します。
[目次を開く]
1. 動的フォームの仕組み
通常、フォームは固定された数の入力フィールド(テキスト、セレクトボックス、チェックボックスなど)で構成されますが、動的フォームではこれらのフィールドを追加・削除して、柔軟に構成することが可能です。動的フォームの典型的なユースケースは、以下のようなシナリオです。
- ユーザーが任意の数のタスクや項目を追加できるリスト
- アンケートで「次の質問を追加」のように、ユーザーが質問を追加可能
- 複数の入力行(氏名、年齢、住所など)を自由に増やすフォーム
動的フォームをReactで実装する場合、フォームの入力状態(state)を管理し、リスト構造やオブジェクトで各フィールドのデータを効率よく扱うのがポイントです。
2. 動的フォームの基本的な実装手順
ここでは、タスク追加用のシンプルな動的フォームを例にとり、Reactでの実装手順を見ていきましょう。
必要な技術要素
- React Hooks:
useStateで状態管理を行います。 - フィールドを追加する際の状態変更。
- リストのマッピングとフォームのレンダリング。
サンプルコード
以下のコードは、動的なタスクリストフォームを作成する例です。
import React, { useState } from "react";
const DynamicForm = () => {
// フォームの各入力フィールドを配列で管理
const [tasks, setTasks] = useState([{ name: "" }]);
// 新しいタスク入力フィールドを追加する関数
const addTask = () => {
setTasks([...tasks, { name: "" }]);
};
// 指定したタスクフィールドを削除する関数
const removeTask = (index) => {
const updatedTasks = tasks.filter((_, i) => i !== index);
setTasks(updatedTasks);
};
// フィールドの値を更新する関数
const handleInputChange = (index, event) => {
const updatedTasks = tasks.map((task, i) =>
i === index ? { ...task, name: event.target.value } : task
);
setTasks(updatedTasks);
};
// フォームの送信時の処理
const handleSubmit = (event) => {
event.preventDefault();
console.log("Submitted tasks:", tasks);
};
return (
<form onSubmit={handleSubmit}>
{tasks.map((task, index) => (
<div key={index}>
<input
type="text"
placeholder={`Task ${index + 1}`}
value={task.name}
onChange={(event) => handleInputChange(index, event)}
/>
<button type="button" onClick={() => removeTask(index)}>
削除
</button>
</div>
))}
<button type="button" onClick={addTask}>
タスクを追加
</button>
<button type="submit">送信</button>
</form>
);
};
export default DynamicForm;
コードの解説
- 状態の初期化
useStateでtasksという配列を管理しています。各タスクはオブジェクトとして格納され、ここではシンプルにnameフィールドだけを持っています。 - タスクの追加
addTask関数で、既存のtasks配列をスプレッド演算子で展開し、新しい空のタスクオブジェクトを追加します。setTasksで更新して再レンダリングします。 - タスクの削除
removeTask関数では、指定されたインデックス以外の要素をfilterで抽出してtasksを更新します。 - 入力値の変更
handleInputChange関数は、mapで配列内のオブジェクトを更新し、特定のインデックスのオブジェクトのnameフィールドだけを変更しています。 - フォーム送信
handleSubmit関数で、フォームが送信されると現在のtasks配列がコンソールに出力されます。APIへの送信や、Reduxなどのグローバル状態に保存するなどの実装もここで行えます。
3. バリデーションとエラーハンドリング
動的フォームには、各フィールドの値をチェックするバリデーション機能が必要な場合があります。以下のような方法で実装が可能です。
const handleSubmit = (event) => {
event.preventDefault();
// バリデーション: 空欄のタスクがないかチェック
const hasEmptyField = tasks.some((task) => task.name.trim() === "");
if (hasEmptyField) {
alert("すべてのタスクに名前を入力してください。");
return;
}
console.log("Submitted tasks:", tasks);
}; handleSubmit関数内で、someメソッドを使ってタスク名が空白のフィールドがないかをチェックし、エラー時にはアラートを表示します。
4. 応用: 入力フィールドの種類を動的に変える
さらに応用として、各フィールドの種類を変えたい場合には、以下のようにタスクオブジェクトにタイプを持たせ、タイプごとに異なる入力をレンダリングすることが可能です。
{tasks.map((task, index) => (
<div key={index}>
{task.type === "text" ? (
<input
type="text"
placeholder={`Task ${index + 1}`}
value={task.name}
onChange={(event) => handleInputChange(index, event)}
/>
) : (
<input
type="number"
placeholder={`Number ${index + 1}`}
value={task.name}
onChange={(event) => handleInputChange(index, event)}
/>
)}
<button type="button" onClick={() => removeTask(index)}>
削除
</button>
</div>
))} task.typeを条件分岐させ、typeがtextの場合はテキスト入力、それ以外の場合は数値入力フィールドを表示します。
まとめ
Reactを使った動的フォームの実装方法を紹介しました。ユーザーが自由にフィールドを増減できるフォームは、利便性が高く、インタラクティブなWebアプリケーションで役立ちます。ReactのuseStateとmap、filterなどを組み合わせることで、簡単に動的フォームが構築可能です。ぜひ、実際のプロジェクトに取り入れてみてください。

