Home / คำแนะนำ / โต้ตอบการรวมแบบฟอร์มการติดต่อ (แอป Vite และหน้าเดียว)
คู่มือการบูรณาการ · REACT & SPA

โต้ตอบการรวมแบบฟอร์มการติดต่อ (แอป Vite และหน้าเดียว)

วิธีเพิ่มแบบฟอร์มการติดต่อและข้อเสนอแนะเพื่อ React Single-Page Applications (SPA) ที่สร้างด้วย Vite หรือ Create React App ซึ่งมีการป้องกันสแปม honeypot และการแจ้งเตือนกล่องจดหมายทันที

1. ส่วนประกอบฟอร์มหน้าสัมผัสปฏิกิริยามาตรฐานพร้อม Vite

ส่วนประกอบ React แบบน้ำหนักเบานี้ใช้ React hooks มาตรฐาน (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

โมเดลการส่ง JSON มาตรฐาน Lugatu ผสานรวมกับไลบรารีการตรวจสอบความถูกต้องของแบบฟอร์ม เช่น 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. ตัวแปรสภาพแวดล้อมและการแยกความลับในปฏิกิริยา

ใน Vite ตัวแปรสาธารณะจะขึ้นต้นด้วย VITE_ ใช้ VITE_LUGATU_FORM_ID สำหรับ ID แบบฟอร์มสาธารณะ อย่าเปิดเผยคีย์ API แบบเซิร์ฟเวอร์ต่อเซิร์ฟเวอร์ (lug_live_...) ภายในซอร์สโค้ดหรือที่เก็บฝั่งไคลเอ็นต์

warning

คีย์ Live API ที่ขึ้นต้นด้วย lug_live_ ถูกสงวนไว้อย่างเคร่งครัดสำหรับการดำเนินการแบบเซิร์ฟเวอร์ถึงเซิร์ฟเวอร์ คำขอเบราว์เซอร์ใด ๆ ที่ส่งด้วยคีย์ 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 ใด ๆ สามารถทำให้ค่าเป็นอนุกรมและส่งไปยังจุดสิ้นสุดสาธารณะได้

พร้อมที่จะสร้างจุดสิ้นสุดของแบบฟอร์มแล้วหรือยัง?

เริ่มต้นฟรีในไม่กี่วินาที ไม่ต้องใช้บัตรเครดิต

เริ่มฟรี →