Home / Mga gabay / React Contact Form Integration (Vite at Single-Page Apps)
GABAY SA PAGSASAMA · REACT & SPA

React Contact Form Integration (Vite at Single-Page Apps)

Paano magdagdag ng mga form ng contact at feedback sa React Single-Page Applications (SPA) na binuo gamit ang Vite o Create React App, na nagtatampok ng honeypot spam defense at mga instant na notification sa inbox.

1. Standard React Contact Form Component na may Vite

Gumagamit ang magaan na bahagi ng React na ito ng mga karaniwang React hook (useState) at ang browser Fetch API upang direktang isumite sa iyong pampublikong endpoint sa Lugatu. Walang kinakailangang external na form na library o backend server.

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. Pagsasama sa React Hook Form at Formik

Ang karaniwang modelo ng pagsusumite ng JSON ng Lugatu ay madaling isinasama sa mga library ng pagpapatunay ng form tulad ng React Hook Form, Formik, o Zod. Direktang ipasa ang mga serialized na value sa field na payload object.

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. Environment Variable at Secret Separation in React

Sa Vite, ang mga pampublikong variable ay may prefix na VITE_. Gamitin ang VITE_LUGATU_FORM_ID para sa pampublikong form ID. Huwag kailanman ilantad ang iyong server-to-server API key (lug_live_...) sa loob ng source code o mga repository sa panig ng kliyente.

warning

Ang mga live na API key na nagsisimula sa lug_live_ ay mahigpit na nakalaan para sa server-to-server execution. Ang anumang kahilingan sa browser na ipinadala gamit ang isang live na API key ay tinatanggihan gamit ang HTTP 403.

Invariant ng Seguridad at Pagpapatotoo

Invariant ng Seguridad: Huwag kailanman i-prefix ang mga live na API key gamit ang VITE_ o REACT_APP_. Ang mga kliyente ng browser ay dapat na eksklusibong magsumite sa mga pampublikong endpoint na walang mga API key.

Pag-troubleshoot at Mga Karaniwang Error sa Pag-ingest

Ang mga pagsusumite ng form ay nagbabalik ng CORS error sa browser console

Tiyaking nagsusumite ka sa pampublikong endpoint (https://www.lugatu.com/api/v1/public/forms/YOUR_PUBLIC_FORM_ID/submissions). Ang mga endpoint ng server-to-server (POST /api/v1/forms/{id}/submissions) ay tahasang hinaharangan ang mga pinagmulan ng browser.

Mga Madalas Itanong

Maaari ba akong gumamit ng React Hook Form o Formik sa Lugatu?

Oo. Tinatanggap ng Lugatu ang karaniwang JSON na may field na object. Maaaring i-serialize ng anumang library ng React form ang mga value nito at isumite sa pampublikong endpoint.

Handa nang gawin ang endpoint ng iyong form?

Magsimula nang libre sa ilang segundo. Walang kinakailangang credit card.

Magsimula nang Libre →