Hydration mismatch emoji terjadi ketika markup HTML hasil SSR menampilkan emoji atau glyph tertentu lalu client JavaScript merender ulang dengan glyph yang berbeda—sering karena fallback font, variasi Unicode, atau state yang belum dinormalisasi. Artikel ini menjelaskan cara mendeteksi dan memperbaiki mismatch tersebut dengan strategi DevTools, preload font/emoji, serta memastikan logika rendering SSR dan client mengeluarkan output deterministik agar UI tetap konsisten.

Misalnya proposal emoji yang ditolak dari Charlotte Buff menyorot glyph yang tidak standar di banyak platform; jika SSR memilih glyph alternatif sementara client memilih fallback lain, hydration error dapat muncul tanpa peringatan. Pendekatan berikut menjaga UI tetap menyatu.

1. Diagnosa mismatch menggunakan DevTools

Langkah pertama adalah menangkap perbedaan sebelum hydration gagal. Buka DevTools, aktifkan tab Elements dan cari element bertanda data-hydration. Bandingkan HTML yang disajikan server dengan DOM yang akhirnya muncul setelah React/Framework lain melakukan hydrate.

Perhatikan tiga hal utama:

  • Glyph/emoji yang berbeda: cek teks yang memiliki emoji atau character yang berpotensi bergantung pada font.
  • Class atau state attribute: pastikan atribut yang dihasilkan server juga dihitung sama di client.
  • JavaScript console: error hydration (misalnya warning React tentang mismatch) memberi tanda; catat elemen mana.

Jika mismatch bermula dari emoji, perhatikan apakah server mengeluarkan kode Unicode tertentu tetapi client di browser memakai fallback font lain. Perbedaan ini sering terlihat sebagai emoji yang mirip tapi berbeda detail rendering.

2. Strategi preload font dan emoji untuk konsistensi glyph

Glyph Discord, WhatsApp, atau emoji sistem bisa berbeda. Untuk menghindari perbedaan, pastikan browser memiliki akses ke font yang sama selama SSR dan client render. Langkah praktis:

  • Preload font dari server: tambah <link rel="preload" href="/fonts/EmojiFont.woff2" as="font" type="font/woff2" crossorigin> di <head>.
  • Gunakan @font-face dengan font fallback eksplisit: deklarasi harus mencakup unicode-range yang relevan agar emoji khusus selalu diambil dari file font yang sama.
  • Sesuaikan font-display: font-display: swap memastikan glyph tersedia cepat tanpa menunggu; pastikan SSR sudah me-render dengan font yang sama.

Contoh konfigurasi Next.js di pages/_document.tsx:

  <Head>
    <link rel="preload" href="/fonts/NotoEmoji-Regular.woff2" as="font" type="font/woff2" crossOrigin="anonymous"/>
    <style>
      @font-face {
        font-family: 'Noto Emoji';
        src: url('/fonts/NotoEmoji-Regular.woff2') format('woff2');
        unicode-range: U+1F300-1F5FF;
        font-display: swap;
      }
    </style>
  </Head>

Dengan preload, server-side render menggunakan font yang sama sehingga markup awal memuat glyph konsisten dengan client.

3. Normalisasi state dan deterministic rendering

Hydration mismatch sering terjadi karena state atau data yang belum uniform antara server dan client. Pastikan data yang memengaruhi emoji/badge dipersiapkan dengan deterministic order di kedua sisi.

Contoh sederhana Next.js dengan data yang memengaruhi emoji:

const emojiByStatus = {
  neutral: '🙂',
  warning: '⚠️',
  error: '❌',
};

export function StatusBadge({ status }: { status: 'neutral' | 'warning' | 'error' }) {
  const normalizedStatus = status in emojiByStatus ? status : 'neutral';
  return (
    <span aria-label={`status ${normalizedStatus}`}>{emojiByStatus[normalizedStatus]}</span>
  );
}

Langkah-langkah penting:

  • Gunakan mapping deterministik: hindari perhitungan yang tergantung pada waktu atau random saat SSR; gunakan struktur tetap.
  • Normalisasi input (contoh: default ke 'neutral' jika status tidak dikenali) agar server dan client mengambil path logika yang sama.
  • Hindari Date.now() atau Math.random() untuk menentukan emoji kecuali disajikan sebagai efek client-only yang tidak dihydrate.

4. Praktik pencegahan lain dan debugging tambahan

  • Gunakan aria-label untuk emoji: simulasi dan pengujian snapshot lebih mudah jika ada label yang konsisten.
  • Bandingkan snapshot server vs client: di testing suite (misalnya Jest), render server dan client lalu bandingkan string output.
  • Pisahkan logika client-only: jika emoji hanya relevan di client (misalnya dipilih dari font sistem), bungkus dengan useEffect dan render fallback sinambung untuk SSR agar tidak memicu mismatch.

Debugging tambahan: gunakan tab Network untuk memastikan file font yang sama di-download di SSR dan client, serta cek Performance untuk melihat apakah rebuild SSR menulis glyph berbeda setelah font fallback berubah.

5. Kesimpulan

Hydration mismatch emoji bisa dihindari dengan memastikan server dan client memakai glyph yang sama melalui preload font/emoji, menormalisasi data, dan menjamin logika render bersifat deterministik. Gunakan DevTools untuk diagnosa cepat dan jadikan error yang mungkin terlihat seperti glyph kecil sebagai indikasi masalah rendering state. Pendekatan sistematis ini menghindarkan UI dari kebingungan yang dipicu glyph tak konsisten.