本記事では、Reactを使ったお問い合わせフォームの作成方法を紹介します。このフォームは、Vue.jsとPHPで作るお問い合わせフォームを元に、Reactで実装したものです。
使用技術とバージョン情報
- React: 17.x (CDN経由で最新バージョンを使用 ※テストは17.0.2)
- Tailwind CSS: 3.x (CDN経由で最新バージョンを使用 ※テストは3.4.15)
- PHP: 8.2.22
- サーバー環境: エックスサーバー
Vue.js版との違い
React版のフォームは、Vue.js版と見た目や動きは同じですが、以下の点が異なります:
- Reactの特性を活用:
- JSXによる宣言的なUI記述。
- コンポーネントの状態を
useState
で管理。
- 同様の動作:
- 入力画面、確認画面、完了画面の3ステップ構成。
- PHPを利用したバックエンド処理。
- ファイル構成:
- ReactとBabelを使用し、HTML内にJSXを記述。
完成するフォームの特徴
- 3ステップ構成:
- 入力画面: 名前、メールアドレス、お問い合わせ内容を入力。
- 確認画面: 入力内容を確認して送信または修正が可能。
- 完了画面: 問い合わせ送信完了のメッセージを表示。
- レスポンシブ対応:
- Tailwind CSSを活用して、PC・タブレット・スマートフォンでも見やすいデザイン。
- Reactによるリアクティブな画面遷移:
- 現在のフォームステップを管理し、適切なコンポーネントをレンダリング。
動きの説明
Reactを使用したフォームは以下の3つのステップで動作します:
- 入力画面
ユーザーは名前、メールアドレス、お問い合わせ内容を入力します。useState
で入力値をリアルタイムに管理します。 - 確認画面
入力された内容を確認し、修正が必要な場合は戻ることができます。問題がなければ「送信する」をクリック。 - 完了画面
問い合わせが送信されると「送信完了」メッセージが表示されます。フォームをリセットして最初の画面に戻ることも可能です。
スクリーンショット
入力画面
確認画面
完了画面
フロントエンドの実装
以下は、Reactを使用したフロントエンドのコードです。
index.html
ReactとTailwind CSSをCDN経由で読み込み、フォームの動作をブラウザ上で確認できるようにします。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React お問い合わせフォーム</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body class="bg-gray-100 min-h-screen flex items-center justify-center">
<div id="root" class="container mx-auto p-4 max-w-screen-md"></div>
<script type="text/babel">
const { useState } = React;
function App() {
const [currentStep, setCurrentStep] = useState("input");
const [formData, setFormData] = useState({
name: "",
email: "",
message: ""
});
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
const resetForm = () => {
setFormData({ name: "", email: "", message: "" });
setCurrentStep("input");
};
const submitForm = async () => {
try {
const response = await fetch("backend/contact.php", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(formData)
});
const data = await response.json();
if (data.success) {
setCurrentStep("complete");
} else {
alert("送信に失敗しました: " + (data.error || "不明なエラー"));
setCurrentStep("input");
}
} catch (error) {
alert("エラーが発生しました。");
setCurrentStep("input");
}
};
return (
<div className="bg-white shadow-md rounded p-6 w-full max-w-md mx-auto">
{currentStep === "input" && (
<>
<h1 className="text-2xl font-bold mb-4">お問い合わせフォーム</h1>
<form
onSubmit={(e) => {
e.preventDefault();
setCurrentStep("confirm");
}}
>
<div className="mb-4">
<label htmlFor="name" className="block text-sm font-medium text-gray-700">名前:</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleInputChange}
required
className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500"
/>
</div>
<div className="mb-4">
<label htmlFor="email" className="block text-sm font-medium text-gray-700">メールアドレス:</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleInputChange}
required
className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500"
/>
</div>
<div className="mb-4">
<label htmlFor="message" className="block text-sm font-medium text-gray-700">お問い合わせ内容:</label>
<textarea
id="message"
name="message"
value={formData.message}
onChange={handleInputChange}
required
className="mt-1 block w-full border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500"
/>
</div>
<button
type="submit"
className="w-full bg-indigo-600 text-white py-2 px-4 rounded hover:bg-indigo-700"
>
確認画面へ
</button>
</form>
</>
)}
{currentStep === "confirm" && (
<>
<h1 className="text-2xl font-bold mb-4">内容の確認</h1>
<p className="mb-2"><strong>名前:</strong> {formData.name}</p>
<p className="mb-2"><strong>メールアドレス:</strong> {formData.email}</p>
<p className="mb-4"><strong>お問い合わせ内容:</strong> {formData.message}</p>
<div className="flex space-x-4">
<button
onClick={() => setCurrentStep("input")}
className="w-1/2 bg-gray-600 text-white py-2 px-4 rounded hover:bg-gray-700"
>
戻る
</button>
<button
onClick={submitForm}
className="w-1/2 bg-indigo-600 text-white py-2 px-4 rounded hover:bg-indigo-700"
>
送信する
</button>
</div>
</>
)}
{currentStep === "complete" && (
<>
<h1 className="text-2xl font-bold mb-4">送信が完了しました</h1>
<p>お問い合わせいただきありがとうございます。</p>
<button
onClick={resetForm}
className="mt-4 w-full bg-indigo-600 text-white py-2 px-4 rounded hover:bg-indigo-700"
>
フォームに戻る
</button>
</>
)}
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
</script>
</body>
</html>
バックエンドの実装
バックエンドでは、PHPを使用して問い合わせ内容を処理します。
contact.php
<?php
header('Content-Type: application/json');
$data = json_decode(file_get_contents('php://input'), true);
if (empty($data['name']) || empty($data['email']) || empty($data['message'])) {
echo json_encode(['success' => false, 'error' => '入力内容が不完全です。']);
exit;
}
// 管理者への通知メール
$toAdmin = 'admin@example.com'; // 仮の送信先アドレス
$subjectAdmin = 'お問い合わせフォームからのメッセージ';
$messageAdmin = "名前: {$data['name']}\nメールアドレス: {$data['email']}\nメッセージ: {$data['message']}";
$headersAdmin = 'From: noreply@example.com'; // 仮のFromアドレス
$mailToAdmin = mail($toAdmin, $subjectAdmin, $messageAdmin, $headersAdmin);
// 問い合わせ者への自動返信メール
$toUser = $data['email'];
$subjectUser = 'お問い合わせありがとうございます';
$messageUser = "{$data['name']} 様\n\nお問い合わせありがとうございます。\n以下の内容で受け付けました。\n----------------------\nお名前: {$data['name']}\nメールアドレス: {$data['email']}\nお問い合わせ内容:\n{$data['message']}\n----------------------\n\n担当者より折り返しご連絡いたします。";
$headersUser = 'From: noreply@example.com'; // 仮のFromアドレス
$mailToUser = mail($toUser, $subjectUser, $messageUser, $headersUser);
if ($mailToAdmin && $mailToUser) {
echo json_encode(['success' => true]);
} else {
echo json_encode(['success' => false, 'error' => 'メール送信に失敗しました。']);
}
まとめ
本記事では、Vue.jsとPHPで作るお問い合わせフォームのReact版を紹介しました。Reactの特徴であるJSXや状態管理を活用しながら、Tailwind CSSとPHPを組み合わせて簡単かつ柔軟なフォームを構築できます。
コメント