Penyepaduan Bahagian Belakang Borang Next.js (Penghala Apl & Tindakan Pelayan)
Panduan pelaksanaan TypeScript dan React yang lengkap untuk mengendalikan borang hubungan dalam Next.js 14/15 menggunakan titik akhir Lugatu dan Tindakan Pelayan dengan pendedahan kelayakan sifar.
1. Seni Bina Penghala Aplikasi Next.js dengan Tindakan Pelayan
Tindakan Pelayan Next.js dilaksanakan secara eksklusif pada pelayan, menjadikannya sesuai untuk menyerahkan pertanyaan dengan kunci API Lugatu peribadi tanpa mendedahkan rahsia dalam berkas klien.
'use server';
export async function submitContact(prevState: any, formData: FormData) {
// Silent rejection of automated bot submissions via honeypot trap
const honeypot = (formData.get('_gotcha') as string) || '';
if (honeypot) {
return { success: true, error: null };
}
const name = formData.get('name') as string;
const email = formData.get('email') as string;
const message = formData.get('message') as string;
if (!name || !email || !message) {
return { success: false, error: 'All fields are required.' };
}
const payload = {
fields: { name, email, message },
};
try {
const res = await fetch(`https://www.lugatu.com/api/v1/forms/${process.env.LUGATU_FORM_ID}/submissions`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LUGATU_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify(payload),
});
if (!res.ok) {
return { success: false, error: 'Failed to submit form.' };
}
return { success: true, error: null };
} catch (err) {
return { success: false, error: 'Network error occurred.' };
}
}
2. Komponen Borang Sebelah Pelanggan dengan Keadaan Memuatkan
Sambungkan Tindakan Pelayan anda kepada komponen klien React 19 / Next.js dengan penunjuk pemuatan yang boleh diakses.
'use client';
import { useActionState } from 'react';
import { submitContact } from '@/app/actions/contact';
export function ContactForm() {
const [state, formAction, isPending] = useActionState(submitContact, { success: false, error: null });
return (
<form action={formAction} className="space-y-4 max-w-md">
<div>
<label className="block text-sm font-semibold mb-1">Name</label>
<input name="name" required className="w-full border rounded-xl p-2.5" />
</div>
<div>
<label className="block text-sm font-semibold mb-1">Email</label>
<input type="email" name="email" required className="w-full border rounded-xl p-2.5" />
</div>
<div>
<label className="block text-sm font-semibold mb-1">Message</label>
<textarea name="message" rows={4} required className="w-full border rounded-xl p-2.5" />
</div>
<input type="text" name="_gotcha" style={{ display: 'none' }} tabIndex={-1} autoComplete="off" />
<button type="submit" disabled={isPending} className="btn-primary-editorial w-full py-2.5">
{isPending ? 'Sending...' : 'Send Message'}
</button>
{state.success && <p className="text-emerald-700 text-sm">Thank you! Your message was received.</p>}
{state.error && <p className="text-red-700 text-sm">{state.error}</p>}
</form>
);
}
Keselamatan & Pengesahan Invarian
Arahan Keselamatan: Jangan sekali-kali meletakkan awalan LUGATU_API_KEY dengan NEXT_PUBLIC_. Hanya pembolehubah sisi pelayan peribadi boleh memegang kunci API langsung anda dengan selamat.
Menyelesaikan masalah & Ralat Pengingesan Biasa
Anda sedang membuat panggilan fetch() daripada kod penyemak imbas sisi klien dengan kunci API. Sama ada bertukar kepada Tindakan Pelayan Next.js atau gunakan titik akhir borang awam tanpa kunci API.
Soalan Lazim
Bolehkah saya menggunakan ini ke Vercel atau Cloudflare Pages?
ya. Tindakan Pelayan berfungsi dengan lancar merentas platform tanpa pelayan dan masa jalan tepi yang disokong oleh Next.js.
Bersedia untuk membuat titik akhir borang anda?
Bermula secara percuma dalam beberapa saat. Tiada kad kredit diperlukan.