Mengatasi UI Terduplikasi di Next.js saat Hydration SSR Gagal adalah tantangan yang muncul ketika HTML hasil render server tidak cocok dengan DOM yang dihasilkan React di klien. Untuk menyelesaikan masalah ini, identifikasi sumber mismatch state, bandingkan nilai server dan client secara eksplisit, lalu gunakan alat debugging seperti React DevTools dan warning hydration.

Kenali gejala UI terduplikasi saat hydration gagal

Gejala umum adalah tampilan komponen muncul dua kali, teks berganti setelah render pertama, atau console menampilkan pesan Text content did not match. Inilah indikator DOM server berbeda dengan DOM klien.

  • Perhatikan console warning yang menyebutkan hydration failed atau Text content did not match.
  • Gunakan view source untuk melihat HTML SSR dan bandingkan dengan DOM akhir di DevTools.
  • Ketika komponen memiliki state terinisialisasi berbeda antara server dan klien (misalnya waktu, nilai random, hasil fetch yang bergantung session), React akan membuang markup awal dan render ulang seluruh subtree.

Membandingkan state SSR vs klien secara sistematis

Perbedaan state adalah akar penyebabnya. Gunakan pola berikut untuk mendeteksi perbedaan:

  1. Tampilkan snapshot props dari getServerSideProps atau getStaticProps dengan console.log('SSR data', data).
  2. Setelah hydration selesai, bandingkan dengan state klien dalam komponen menggunakan useEffect.

Contoh pendekatan:

export default function Beranda({ initialItems }) {
  const [items, setItems] = useState(initialItems);
  useEffect(() => {
    if (JSON.stringify(items) !== JSON.stringify(initialItems)) {
      console.warn('Mismatch antara state SSR dan client', { initialItems, items });
    }
  }, [initialItems, items]);
  // render tetap deterministik
}

Penting: jangan gunakan JSON.stringify pada objek besar di produksi; teknik tersebut untuk debugging saja. Tujuannya memastikan nilai awal dari server dan klien identik.

Menelusuri props dan efek samping yang menyebabkan mismatch

Cek pola berikut yang sering memicu mismatch:

  • State yang diinisialisasi dari Date.now(), Math.random(), atau nilai yang bergantung environment (cookie, localStorage).
  • Efek samping di useEffect yang menjalankan fetch dan langsung mengubah state tanpa memastikan deterministik render pertama.
  • Rendering berdasarkan hook seperti useMediaQuery atau browser APIs yang hanya tersedia di client.

Solusinya:

  • Jadikan render server deterministik dengan menghindari side-effect saat render awal. Jika perlu, render fallback dan update via useEffect setelah hydration.
  • Gunakan penanda seperti const isBrowser = typeof window !== 'undefined' sebelum memanggil API browser.
  • Untuk data dinamis, pertimbangkan placeholder SSR lalu isi ulang melalui useEffect tanpa mengganti markup awal yang sudah dirender.

Debugging dengan React DevTools, warning, dan log hydration

React DevTools memiliki tab Components untuk memeriksa props dan state aktual setelah hydration. Di situ, cari komponen yang mengalami perubahan drastis jumlah child atau props.

Tips debugging tambahan:

  • Aktifkan next dev dan cari warning hydration di console browser. Warning ini memberi tahu komponen mana yang gagal.
  • Gunakan React.StrictMode selama development untuk menangkap efek samping tidak diinginkan yang bisa memicu mismatch.
  • Tuliskan console.trace() ketika mismatch terdeteksi untuk melihat rutin mana yang men-trigger perubahan state.

Checklist mitigasi dan praktik terbaik pengambilan data SSRed

  • Deterministik: Pastikan data dari SSR tidak mengandung nilai yang berbeda setiap render (hindari Math.random(), token waktu).
  • Inisialisasi state: Gunakan props SSR sebagai nilai awal useState, lalu hanya ubah state di client jika nilai baru didapat.
  • Pemisahan logika: Tempatkan logika window-only di useEffect sehingga tidak dijalankan di server.
  • Pengambilan data: Potong data yang berubah-ubah, lalu lakukan fetch ulang di client dengan useSWR atau fetch manual sambil mempertahankan markup SSR.
  • Validasi: Tambahkan unit/integration test yang melakukan snapshot SSR dan render client untuk memastikan konsistensi di waktu build.

Checklist ini membantu tim menjaga state tetap deterministik dan menghindari efek samping yang menyebabkan UI terduplikasi saat hydration gagal.

Kesimpulan

Hydration mismatch di Next.js sering terjadi karena nilai state antara server dan client berbeda. Dengan membandingkan props, menelusuri efek samping, memanfaatkan React DevTools, serta menerapkan checklist mitigasi tersebut, Anda bisa memperkecil atau menghilangkan UI terduplikasi. Fokus pada determinisme data SSR serta logika client-only akan membuat render lebih stabil dan mengurangi kebutuhan fallback penuh setelah hydration.