Home / Guias / Integração de formulário de contato React (aplicativos Vite e de página única)
GUIA DE INTEGRAÇÃO · REACT & SPA

Integração de formulário de contato React (aplicativos Vite e de página única)

Como adicionar formulários de contato e feedback a aplicativos React de página única (SPA) desenvolvidos com Vite ou Create React App, apresentando defesa contra spam honeypot e notificações instantâneas na caixa de entrada.

1. Componente padrão do formulário de contato React com Vite

Este componente React leve usa ganchos React padrão (useState) e a API Fetch do navegador para enviar diretamente ao seu endpoint público Lugatu. Não são necessárias bibliotecas de formulários externas ou servidores back-end.

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. Integração com React Hook Form e Formik

O modelo de envio JSON padrão Lugatu integra-se facilmente com bibliotecas de validação de formulários como React Hook Form, Formik ou Zod. Passe os valores serializados diretamente para o objeto de carga útil dos campos.

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. Variáveis ​​de ambiente e separação secreta no React

No Vite, as variáveis ​​públicas são prefixadas com VITE_. Use VITE_LUGATU_FORM_ID para o ID do formulário público. Nunca exponha sua chave de API de servidor para servidor (lug_live_...) dentro do código-fonte ou repositórios do lado do cliente.

warning

As chaves de API Live começando com lug_live_ são estritamente reservadas para execução de servidor para servidor. Qualquer solicitação do navegador enviada com uma chave de API ativa é rejeitada com HTTP 403.

Invariante de segurança e autenticação

Invariante de segurança: nunca prefixe chaves de API ativas com VITE_ ou REACT_APP_. Os clientes do navegador devem enviar exclusivamente para endpoints públicos sem chaves de API.

Solução de problemas e erros comuns de ingestão

Os envios de formulários retornam erro CORS no console do navegador

Certifique-se de enviar para o endpoint público (https://www.lugatu.com/api/v1/public/forms/YOUR_PUBLIC_FORM_ID/submissions). Os endpoints de servidor para servidor (POST /api/v1/forms/{id}/submissions) bloqueiam explicitamente as origens do navegador.

Perguntas frequentes

Posso usar React Hook Form ou Formik com Lugatu?

Sim. Lugatu aceita JSON padrão com um objeto de campos. Qualquer biblioteca de formulários React pode serializar seus valores e enviá-los ao endpoint público.

Pronto para criar o endpoint do seu formulário?

Comece gratuitamente em segundos. Não é necessário cartão de crédito.

Comece grátis →