Form dengan Server Actions
Membangun form lengkap: pending state, pesan sukses, dan reset form setelah submit.
Form tanpa JavaScript pun jalan
Karena Server Action terikat ke atribut action bawaan HTML, form tetap berfungsi walau JavaScript dimatikan. Browser melakukan POST biasa dan Next.js menangani sisanya. Ini fondasi yang kokoh, lalu kita poles UX-nya.
Pending state
Tampilkan status loading saat form diproses dengan hook useFormStatus:
// app/kontak/tombol.tsx
"use client";
import { useFormStatus } from "react-dom";
export function TombolKirim() {
const { pending } = useFormStatus();
return (
<button type="submit" disabled={pending}>
{pending ? "Mengirim..." : "Kirim"}
</button>
);
}useFormStatus harus dipakai di komponen terpisah (tidak bisa di komponen yang sama dengan <form>), karena ia membaca status form induknya.
Pesan sukses dan reset
Gabungkan useActionState untuk pesan hasil, dan reset form setelah sukses:
"use client";
import { useActionState, useRef } from "react";
import { kirimPesan } from "./actions";
import { TombolKirim } from "./tombol";
export default function FormKontak() {
const formRef = useRef<HTMLFormElement>(null);
const [state, action] = useActionState(async (prev: unknown, fd: FormData) => {
const hasil = await kirimPesan(fd);
if (hasil.sukses) formRef.current?.reset();
return hasil;
}, null);
return (
<form ref={formRef} action={action}>
<input name="nama" placeholder="Nama" required />
<textarea name="pesan" placeholder="Pesan" required />
<TombolKirim />
{state?.sukses && <p>Pesan terkirim, terima kasih!</p>}
</form>
);
}Kesalahan umum pemula
- Memakai
useFormStatusdi komponen yang sama dengan<form>. Hook ini membaca status form induk, jadi harus di komponen anak (misal komponen tombol terpisah). - Lupa
revalidatePathsetelah mutasi. Data tersimpan tapi halaman masih menampilkan data lama. Panggil revalidasi di dalam action. - Tidak men-disable tombol saat pending. User bisa double-submit dan membuat data ganda. Selalu disable tombol saat
pending.
Latihan singkat
- Buat form tambah todo dengan tombol yang menampilkan "Menyimpan..." saat pending dan disable selama proses.
- Setelah todo tersimpan, reset form otomatis dan tampilkan pesan sukses yang hilang setelah 3 detik.
Rangkuman
useFormStatusmemberi statuspending; dipakai di komponen tombol terpisah.useActionStatemengelola hasil action dan menampilkannya di form.- Reset form setelah sukses dan panggil
revalidatePathagar data diperbarui. - Selalu disable tombol saat pending untuk mencegah double-submit.
Catatan teknis: Setelah action yang mengubah data, panggil
revalidatePathdi dalam Server Action agar halaman yang menampilkan data tersebut diperbarui. Tanpa ini, user bisa melihat data lama walau simpannya sudah sukses.