Kenapa Geolocation Gagal? Cara Mengatasi Navigator Is Not Defined Next Js

Error navigator is not defined muncul karena kode memanggil navigator.geolocation saat komponen masih dirender di server. Solusi tercepat: pindahkan pemanggilan ke event handler atau useEffect di Client Component, lalu pasang guard typeof navigator !== "undefined".

Penyebab Navigator Is Not Defined di App Router

Next.js App Router merender Server Component di server secara default. Objek navigator hanya tersedia di browser, jadi pemanggilan langsung saat prerender pasti gagal.

  • Server Component tidak punya akses ke browser API seperti geolocation, clipboard, dan mediaDevices.
  • Client Component tetap dirender sekali di server untuk HTML awal, lalu dihydrate di browser.
  • Pola pemicu umum: navigator.geolocation.getCurrentPosition() ditulis langsung di body render.
  • Pola lain: dipakai di initializer useState(() => navigator...) atau dijalankan library peta, fingerprint, dan clipboard saat import.

Tabel Troubleshooting Cepat Navigator Error

Baca stack trace dulu. Nama file dan nomor baris biasanya menunjuk baris pemanggil navigator.

Masalah Penyebab Solusi
Error saat next build Geolocation dipanggil saat prerender Pindah ke useEffect atau event click
Error saat refresh halaman Client Component akses navigator saat render Tambah guard typeof navigator
Error dari library pihak ketiga Library membaca navigator saat import Muat dengan dynamic ssr: false
Error hanya saat navigasi tertentu Kode clipboard/mediaDevices jalan sebelum mount Tunda sampai user berinteraksi

Solusi Aman untuk Akses Navigator di Client

Tambahan "use client" saja tidak cukup. Kode tetap perlu memastikan browser sudah siap.

  1. Buat komponen kecil bertanda "use client" khusus kebutuhan lokasi atau clipboard.
  2. Jangan panggil navigator di body render atau initializer state.
  3. Pasang guard typeof navigator !== "undefined" plus cek fitur, misalnya "geolocation" in navigator.
  4. Panggil geolocation di dalam useEffect atau handler tombol.
  5. Pakai dynamic import ssr: false hanya untuk komponen yang sepenuhnya browser-only.
"use client";
import { useState } from "react";

export default function TombolLokasi() {
  const [status, setStatus] = useState("");

  function mintaLokasi() {
    if (typeof navigator === "undefined" || !("geolocation" in navigator)) {
      setStatus("Geolocation tidak didukung browser ini");
      return;
    }

    navigator.geolocation.getCurrentPosition(
      (pos) => setStatus(`${pos.coords.latitude}, ${pos.coords.longitude}`),
      () => setStatus("Izin lokasi ditolak")
    );
  }

  async function salinTeks() {
    if (typeof navigator === "undefined" || !navigator.clipboard) return;
    await navigator.clipboard.writeText("Halo");
  }

  return <button onClick={mintaLokasi}>{status || "Minta lokasi"}</button>;
}

FAQ

Apakah semua kode navigator harus memakai useEffect?

Tidak. Event handler seperti onClick juga aman karena hanya berjalan di browser.

Kenapa guard typeof window saja belum cukup?

window ada belum tentu fitur tersedia, jadi cek juga "geolocation" in navigator atau navigator.clipboard.

Kapan memakai dynamic import untuk komponen navigator?

Pakai saat library langsung membaca navigator ketika modul diimpor dan tidak bisa diperbaiki dengan guard biasa.