Home / Guides / Intégration du formulaire de contact React (applications Vite et monopage)
GUIDE D'INTÉGRATION · REACT & SPA

Intégration du formulaire de contact React (applications Vite et monopage)

Comment ajouter des formulaires de contact et de commentaires aux applications React Single-Page (SPA) créées avec Vite ou Create React App, avec une défense anti-spam Honeypot et des notifications instantanées dans la boîte de réception.

1. Composant de formulaire de contact React standard avec Vite

Ce composant React léger utilise des hooks React standard (useState) et l'API Fetch du navigateur pour soumettre directement à votre point de terminaison public Lugatu. Aucune bibliothèque de formulaires externe ni serveur principal requis.

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. Intégration avec React Hook Form et Formik

Le modèle de soumission JSON standard de Lugatu s'intègre sans effort aux bibliothèques de validation de formulaire telles que React Hook Form, Formik ou Zod. Transmettez les valeurs sérialisées directement dans l’objet de charge utile des champs.

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. Variables d'environnement et séparation secrète dans React

Dans Vite, les variables publiques sont préfixées par VITE_. Utilisez VITE_LUGATU_FORM_ID pour l'ID du formulaire public. N'exposez jamais votre clé API de serveur à serveur (lug_live_...) dans le code source ou les référentiels côté client.

warning

Les clés API Live commençant par lug_live_ sont strictement réservées à l'exécution de serveur à serveur. Toute requête de navigateur envoyée avec une clé API active est rejetée avec HTTP 403.

Invariant de sécurité et d'authentification

Invariant de sécurité : ne préfixez jamais les clés API en direct avec VITE_ ou REACT_APP_. Les clients du navigateur doivent exclusivement se soumettre à des points de terminaison publics sans clés API.

Dépannage et erreurs d’ingestion courantes

Les soumissions de formulaire renvoient une erreur CORS dans la console du navigateur

Assurez-vous de soumettre au point de terminaison public (https://www.lugatu.com/api/v1/public/forms/YOUR_PUBLIC_FORM_ID/submissions). Les points de terminaison de serveur à serveur (POST /api/v1/forms/{id}/submissions) bloquent explicitement les origines du navigateur.

Foire aux questions

Puis-je utiliser React Hook Form ou Formik avec Lugatu ?

Oui. Lugatu accepte le JSON standard avec un objet field. Toute bibliothèque de formulaires React peut sérialiser ses valeurs et les soumettre au point de terminaison public.

Prêt à créer votre point de terminaison de formulaire ?

Commencez gratuitement en quelques secondes. Aucune carte de crédit requise.

Commencez gratuitement →