Cara Mengakses Window Aman Next Js tanpa Error Hydration

Cara mengakses window aman di Next.js App Router adalah membacanya hanya di Client Component dan hanya di dalam useEffect atau event handler. Server tidak punya objek window, jadi kode yang membacanya saat render memicu error window is not defined.

Kenapa Window Error di Next Js App Router

Server Component di-render di server lebih dulu sebelum dikirim ke browser. Prerender ini berjalan di Node.js tanpa DOM.

Baris seperti const lebar = window.innerWidth di body komponen langsung dieksekusi server. Server tidak mengenal window, proses berhenti dan build atau navigasi gagal.

  • Guard typeof window !== "undefined" berguna untuk kode campuran yang kadang jalan di server.
  • Guard tidak cukup kalau nilai dari window membuat HTML server berbeda dengan HTML awal client.
  • Kode murni browser seperti ukuran layar, scroll, dan localStorage lebih aman dipindah ke efek atau handler.

Pola Aman Mengakses Window di Client Component

Render awal memakai nilai default, lalu browser memperbarui state setelah mount. Ini mencegah hydration mismatch.

  1. Tambahkan "use client" di baris pertama file komponen.
  2. Buat state awal dengan nilai netral, misalnya 0 atau null.
  3. Baca window di dalam useEffect, simpan ke state.
  4. Pasang dan bersihkan resize listener bila nilai harus responsif.
"use client";
import { useEffect, useState } from "react";

export default function LebarLayar() {
  const [lebar, setLebar] = useState(0);

  useEffect(() => {
    const update = () => setLebar(window.innerWidth);
    update();
    window.addEventListener("resize", update);
    return () => window.removeEventListener("resize", update);
  }, []);

  return <p>Lebar layar: {lebar}px</p>;
}
  • Jangan baca window saat render atau sebagai initial value useState.
  • Sinkronkan nilai browser lewat state agar server dan client memulai dari HTML yang sama.
  • Tangani perubahan ukuran dengan listener dan hapus listener saat unmount.

Tabel Pilihan Teknik Akses Window

Teknik Cocok Untuk Catatan
useEffect Ukuran layar, scroll, media query Render awal sama, update setelah mount
Event handler Klik, submit, resize manual Berjalan di browser, tanpa guard tambahan
dynamic ssr false Komponen browser-only Matikan prerender untuk file tersebut

useEffect cocok untuk membaca nilai setelah halaman tampil. Event handler cocok untuk aksi pengguna. Dynamic import cocok ketika seluruh komponen bergantung pada API browser atau library peta dan chart.

import dynamic from "next/dynamic";

const PetaBrowser = dynamic(() => import("./PetaBrowser"), {
  ssr: false,
  loading: () => <p>Memuat peta...</p>,
});

export default function Halaman() {
  return <PetaBrowser />;
}

FAQ

Apakah typeof window cukup di Server Component?

Tidak, Hook dan browser API tetap tidak boleh dipakai di Server Component meski memakai guard tersebut.

Bagaimana membaca ukuran layar tanpa hydration error?

Render nilai default dulu di Client Component, lalu perbarui lewat useEffect setelah mount.

Kapan memakai dynamic dengan ssr false?

Pakai saat seluruh komponen hanya bisa jalan di browser, misalnya peta interaktif atau editor visual.