Cara detect mounted client Next.js dibutuhkan saat render server dan render browser menghasilkan output berbeda. Pola yang benar memakai flag mounted di Client Component: render placeholder yang sama di server, lalu set true di useEffect setelah mount.
Gunakan pola ini hanya untuk bagian kecil yang memang bergantung browser, bukan seluruh halaman. Server tetap mengirim HTML stabil, browser melanjutkan tanpa hydration mismatch.
Kenapa Perlu Deteksi Mounted di Client Component
Server Component dan prerender tidak punya window, document, ukuran layar, atau zona waktu pengguna. Nilai itu baru ada setelah React mount di browser.
Kasus umum yang sering memicu hydration failed:
- Membaca localStorage, tema gelap terang, token tampilan, atau preferensi bahasa.
- Menampilkan tanggal, jam, hitung mundur, angka acak, atau ID yang dibuat saat render.
- Mendeteksi ekstensi browser, ad blocker, lebar viewport, clipboard, atau permission.
Tanda kamu butuh gate mounted:
- Error hilang di refresh tetapi muncul saat navigasi client.
- Teks berubah sepersekian detik setelah halaman tampil.
- Kode memakai browser API langsung di body render.
Pola Mounted Flag dengan useEffect yang Benar
Ikuti langkah ini di Client Component App Router:
- Tambahkan use client di baris pertama file.
- Buat state mounted dengan nilai awal false.
- Set mounted menjadi true di dalam useEffect kosong.
- Render fallback identik selama belum mounted, tampilkan konten browser setelah mounted.
"use client";
import { useEffect, useState } from "react";
export default function Clock() {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
return <p>Memuat waktu...</p>;
}
return <p>{new Date().toLocaleTimeString("id-ID")}</p>;
}
| Kondisi | Render Server | Render Setelah Mount |
|---|---|---|
| Belum mounted | Fallback teks | Tidak dipakai |
| Sudah mounted | Tidak terjadi | Waktu lokal browser |
Kesalahan Umum dan Alternatif Selain Mounted Gate
Jangan mengosongkan seluruh halaman sampai mounted. Layout, judul, dan konten statis harus tetap dikirim server agar cepat dan terbaca crawler.
- Cek typeof window di body render lalu me-return markup berbeda, ini tetap membuat hydration mismatch.
- Memasang useEffect atau useState di Server Component tanpa use client.
- Mematikan SSR untuk banyak komponen hanya karena satu widget bermasalah.
Alternatif yang lebih tepat untuk widget berat khusus browser adalah next/dynamic dengan ssr: false. Untuk perbedaan teks kecil seperti format tanggal, gunakan suppressHydrationWarning secara selektif pada elemen tersebut.
FAQ
Apakah mounted flag menghilangkan hydration error?
Ya, jika server dan render awal client menghasilkan fallback yang sama persis.
Kapan memakai dynamic ssr false?
Pakai saat komponen memakai library browser berat seperti editor, peta, atau grafik interaktif.
Apakah cek mounted aman untuk SEO?
Aman untuk widget kecil, tetapi konten penting harus tetap dirender server agar mudah diindeks.