Home / ガイド / React コンタクト フォームの統合 (Vite およびシングルページ アプリ)
統合ガイド · React & SPA

React コンタクト フォームの統合 (Vite およびシングルページ アプリ)

Vite で構築された React シングルページ アプリケーション (SPA) に問い合わせフォームとフィードバック フォームを追加する方法、またはハニーポット スパム防御機能とインスタント インボックス通知を備えた React App を作成する方法。

1. Vite を使用した標準 React コンタクト フォーム コンポーネント

この軽量の React コンポーネントは、標準の React フック (useState) とブラウザーの Fetch API を使用して、Lugatu パブリック エンドポイントに直接送信します。 外部フォーム ライブラリやバックエンド サーバーは必要ありません。

src/components/ContactForm.tsx tsx
import React, { useState } from 'react';

export function ContactForm() {
  const [formData, setFormData] = useState({ name: '', email: '', message: '', _gotcha: '' });
  const [status, setStatus] = useState<'idle' | 'submitting' | 'success' | 'error'>('idle');
  const [errorMessage, setErrorMessage] = useState('');

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (formData._gotcha) return; // Silent discard for automated bot traps

    setStatus('submitting');
    setErrorMessage('');

    try {
      const response = await fetch('https://www.lugatu.com/api/v1/public/forms/YOUR_PUBLIC_FORM_ID/submissions', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
        body: JSON.stringify({
          fields: {
            name: formData.name,
            email: formData.email,
            message: formData.message,
          },
          honeypot: formData._gotcha,
        }),
      });

      if (!response.ok) {
        throw new Error('Failed to deliver message');
      }

      setStatus('success');
      setFormData({ name: '', email: '', message: '', _gotcha: '' });
    } catch (err: any) {
      setStatus('error');
      setErrorMessage(err.message || 'Submission error. Please try again.');
    }
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4 max-w-md">
      <div>
        <label htmlFor="react-name" className="block text-sm font-semibold mb-1">Your Name</label>
        <input
          id="react-name"
          type="text"
          required
          value={formData.name}
          onChange={(e) => setFormData({ ...formData, name: e.target.value })}
          className="w-full border rounded-xl p-2.5"
        />
      </div>

      <div>
        <label htmlFor="react-email" className="block text-sm font-semibold mb-1">Email Address</label>
        <input
          id="react-email"
          type="email"
          required
          value={formData.email}
          onChange={(e) => setFormData({ ...formData, email: e.target.value })}
          className="w-full border rounded-xl p-2.5"
        />
      </div>

      <div>
        <label htmlFor="react-message" className="block text-sm font-semibold mb-1">Message</label>
        <textarea
          id="react-message"
          rows={4}
          required
          value={formData.message}
          onChange={(e) => setFormData({ ...formData, message: e.target.value })}
          className="w-full border rounded-xl p-2.5"
        />
      </div>

      <!-- Honeypot spam defense -->
      <input
        type="text"
        name="_gotcha"
        value={formData._gotcha}
        onChange={(e) => setFormData({ ...formData, _gotcha: e.target.value })}
        style={{ display: 'none' }}
        tabIndex={-1}
        autoComplete="off"
      />

      <button
        type="submit"
        disabled={status === 'submitting'}
        className="btn-primary-editorial py-2.5 px-6"
      >
        {status === 'submitting' ? 'Sending...' : 'Send Message'}
      </button>

      {status === 'success' && (
        <p className="text-sm text-green-700 font-medium">Thank you! Your message was delivered.</p>
      )}
      {status === 'error' && (
        <p className="text-sm text-red-600">{errorMessage}</p>
      )}
    </form>
  );
}

2. React Hook Form および Formik との統合

Lugatu 標準 JSON 送信モデルは、React Hook Form、Formik、Zod などのフォーム検証ライブラリと簡単に統合します。 シリアル化された値をフィールド ペイロード オブジェクトに直接渡します。

useLugatuForm.ts typescript
// React Hook Form submission handler
const onSubmit = async (data: FormValues) => {
  const res = await fetch(`https://www.lugatu.com/api/v1/public/forms/${import.meta.env.VITE_LUGATU_FORM_ID}/submissions`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ fields: data }),
  });
  return res.ok;
};

3. React における環境変数とシークレットの分離

Vite では、パブリック変数には VITE_ という接頭辞が付きます。 パブリック フォーム ID には VITE_LUGATU_FORM_ID を使用します。 クライアント側のソース コードまたはリポジトリ内でサーバー間 API キー (lug_live_...) を決して公開しないでください。

warning

lug_live_ で始まるライブ API キーは、サーバー間の実行用に厳密に予約されています。 ライブ API キーを使用して送信されたブラウザー リクエストは、HTTP 403 で拒否されます。

セキュリティと認証の不変性

セキュリティの不変条件: ライブ API キーの前に VITE_ または REACT_APP_ を付けないでください。 ブラウザ クライアントは、API キーを使用せずにパブリック エンドポイントに排他的に送信する必要があります。

トラブルシューティングと一般的な取り込みエラー

フォームを送信すると、ブラウザー コンソールで CORS エラーが返されます

パブリック エンドポイント (https://www.lugatu.com/api/v1/public/forms/YOUR_PUBLIC_FORM_ID/submissions) に送信していることを確認してください。 サーバー間エンドポイント (POST /api/v1/forms/{id}/submissions) は、ブラウザーのオリジンを明示的にブロックします。

よくある質問

React Hook Form または Formik を Lugatu で使用できますか?

はい。 Lugatu は、フィールド オブジェクトを含む標準の JSON を受け入れます。 どの React フォーム ライブラリでも、その値をシリアル化し、パブリック エンドポイントに送信できます。

フォームエンドポイントを作成する準備はできましたか?

数秒で無料で始められます。 クレジットカードは必要ありません。

無料で始める →