Hitung Mundur Waktu Nyata & Taburan Kelopak Hati
Menghitung mundur sisa hari, jam, dan menit menuju hari pernikahan secara tepat waktu, dihiasi kelopak hati yang melayang lembut di layar.
Menghitung mundur sisa hari, jam, dan menit menuju hari pernikahan secara tepat waktu, dihiasi kelopak hati yang melayang lembut di layar.
Tantangan & Kebutuhan Pengguna
Pada layar Hero pembuka, dibutuhkan 12 partikel hati yang melayang naik dengan posisi horizontal, ukuran, durasi, waktu tunda, dan ayunan kiri-kanan (`drift`) yang acak. Namun, memanggil `Math.random()` secara langsung di fase render atau di dalam `useMemo` pada komponen Next.js memicu error *Hydration Mismatch* karena nilai acak yang di-render di server berbeda dengan nilai yang dihitung ulang di peramban klien.
Segala kalkulasi non-deterministik seperti Math.random() dan waktu saat ini harus ditangguhkan ke fase pasca-mount di klien agar pohon DOM server dan klien selalu selaras.
Solusi & Cara Kerja
Komponen `FloatingHearts` menginisialisasi daftar partikel sebagai array kosong `useState<Heart[]>([])` sehingga saat pre-rendering di server maupun render awal di klien sama-sama mengembalikan `null`. Tepat setelah komponen terpasang di DOM klien, `useEffect` membangkitkan 12 objek partikel acak yang kemudian dianimasikan oleh Framer Motion menggunakan array keyframe pada sumbu X (`[0, h.drift * 0.4, h.drift, h.drift * 0.6, 0]`) dan rotasi. Prinsip serupa diterapkan pada penghitung waktu mundur menuju `2026-06-07 10:00:00` yang dikalkulasi setiap detik di dalam `useEffect` menggunakan `weddingDate.diff(dayjs())`.
Berikut adalah implementasi `FloatingHearts` bebas hidrasi dan kalkulasi hitung mundur waktu nyata dari `src/pages/HomePage.tsx`:
Detail & Hal yang Diperhatikan
- Eliminasi SSR Hydration Mismatch: Mengganti `useMemo` dengan kombinasi `useState([])` + `useEffect` memastikan HTML awal dari server 100% identik dengan hidrasi pertama React 19 di klien.
- Trajektori ayunan natural: Penggunaan 5 titik keyframe pada sumbu X dan rotasi membuat partikel hati tampak mengayun tertiup angin, bukan bergerak kaku dalam garis lurus.
- Perlindungan waktu kedaluwarsa: Guard clause `if (diff <= 0) return;` pada timer `dayjs` memastikan angka hari, jam, menit, dan detik tetap tertahan di `0` setelah waktu acara terlampaui.
Selalu sematkan kelas `pointer-events-none select-none` pada lapisan partikel melayang agar elemen animasi tidak menangkap event sentuhan atau klik pengguna di layar ponsel.