最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - Next js issue with the browser side apis or react libraries - Stack Overflow

programmeradmin3浏览0评论

I was making a page using the leaflet and next.js

I got this error for just importing the leaflet.

ReferenceError: window is not defined
    at instantiateModule (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:590:23)
    at getOrInstantiateModuleFromParent (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:645:12)
    at esmImport (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:132:20)
    at [project]/src/app/(app)/connect-client-request/[requestId]/page.tsx [app-ssr] (ecmascript) (file://C%3A/Users/Aryan/Documents/Web%20Dev/AutoResQ-Next/autoresq-next/src/app/%28app%29/connect-client-request/%5BrequestId%5D/page.tsx:7:0)
    at instantiateModule (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:590:23)
    at getOrInstantiateModuleFromParent (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:645:12)
    at commonJsRequire (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:147:20)
   5 | import { io, Socket } from "socket.io-client";
   6 | import { useSession } from "next-auth/react";
>  7 | import L from "leaflet";
   8 | import "leaflet/dist/leaflet.css";
   9 | import axios from "axios";
  10 | import { useToast } from "@/hooks/use-toast"; {
  digest: '3246626898'
}

this was my page.tsx

"use client";

import React, { useEffect, useRef, useState, useCallback } from "react";
import L from "leaflet";
import "leaflet/dist/leaflet.css";

interface Coords {
  lat: number;
  long: number;
}

const Page: React.FC = () => {
  const [userCoords, setUserCoords] = useState<Coords | null>(null);
  const [status, setStatus] = useState<string>("Initializing location...");
  const mapRef = useRef<L.Map | null>(null);
  const markersLayerRef = useRef<L.LayerGroup | null>(null);
  const markerRef = useRef<L.Marker | null>(null);
  const watchIdRef = useRef<number | null>(null);

  const initializeMap = useCallback((coords: Coords) => {
    // Prevent reinitializing if map already exists
    if (mapRef.current) {
      // Update existing marker or map view
      markerRef.current?.setLatLng([coords.lat, coords.long]);
      mapRef.current.setView([coords.lat, coords.long], 16);
      return;
    }

    // Create map only once
    const map = L.map("map", {
      center: [coords.lat, coords.long],
      zoom: 16,
      zoomControl: true,
      attributionControl: false
    });

    L.tileLayer("https://{s}.tile.openstreetmap/{z}/{x}/{y}.png", {
      attribution: "© OpenStreetMap contributors",
    }).addTo(map);

    // Create marker
    const customIcon = L.icon({
      iconUrl: ":ANd9GcRLWRQ2MP28ucwL3bUexiJ8kfDjKM_IO6TCrw&s",
      iconSize: [40, 40],
      iconAnchor: [20, 40],
      popupAnchor: [0, -40],
    });

    const marker = L.marker([coords.lat, coords.long], { 
      icon: customIcon 
    }).addTo(map);

    // Store references
    mapRef.current = map;
    markerRef.current = marker;
  }, []);

  useEffect(() => {
    // Geolocation tracking
    if ("geolocation" in navigator) {
      watchIdRef.current = navigator.geolocation.watchPosition(
        (position) => {
          const newCoords: Coords = {
            lat: position.coords.latitude,
            long: position.coords.longitude,
          };

          // Minimal state update
          setUserCoords(prevCoords => {
            // Only update if coordinates have changed significantly
            const hasChanged = !prevCoords || 
              Math.abs(newCoords.lat - prevCoords.lat) > 0.0001 ||
              Math.abs(newCoords.long - prevCoords.long) > 0.0001;

            if (hasChanged) {
              initializeMap(newCoords);
              setStatus(`Location: ${newCoords.lat.toFixed(4)}, ${newCoords.long.toFixed(4)}`);
              return newCoords;
            }

            return prevCoords;
          });
        },
        (error) => {
          const errorMessages = {
            [error.PERMISSION_DENIED]: "Location access denied",
            [error.POSITION_UNAVAILABLE]: "Location information unavailable",
            [error.TIMEOUT]: "Location request timed out"
          };
          
          setStatus(`Error: ${errorMessages[error.code] || "Unknown error"}`);
        },
        {
          enableHighAccuracy: true,
          timeout: 10000,
          maximumAge: 0,
        }
      );
    } else {
      setStatus("Geolocation not supported");
    }

    // Cleanup
    return () => {
      if (watchIdRef.current !== null) {
        navigator.geolocation.clearWatch(watchIdRef.current);
      }
      if (mapRef.current) {
        mapRef.current.remove();
      }
    };
  }, [initializeMap]);

  return (
    <div className="w-full bg-white p-6 rounded-lg shadow-lg space-y-4">
      <p className="text-lg font-semibold text-gray-700">{status}</p>
      <div
        id="map"
        className="h-[80vh] w-full rounded-lg shadow-md border border-gray-200"
      />
    </div>
  );
};

export default Page;

I was very confused why this was not getting built. Also even though it ran on the dev mode but still gave me error.

I was not expecting any error as I already used the "use client" on the page.
Hoping the page would be cool and treated as just client side code.

I was making a page using the leaflet and next.js

I got this error for just importing the leaflet.

ReferenceError: window is not defined
    at instantiateModule (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:590:23)
    at getOrInstantiateModuleFromParent (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:645:12)
    at esmImport (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:132:20)
    at [project]/src/app/(app)/connect-client-request/[requestId]/page.tsx [app-ssr] (ecmascript) (file://C%3A/Users/Aryan/Documents/Web%20Dev/AutoResQ-Next/autoresq-next/src/app/%28app%29/connect-client-request/%5BrequestId%5D/page.tsx:7:0)
    at instantiateModule (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:590:23)
    at getOrInstantiateModuleFromParent (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:645:12)
    at commonJsRequire (C:\Users\Aryan\Documents\Web Dev\AutoResQ-Next\autoresq-next\.next\server\chunks\ssr\[turbopack]_runtime.js:147:20)
   5 | import { io, Socket } from "socket.io-client";
   6 | import { useSession } from "next-auth/react";
>  7 | import L from "leaflet";
   8 | import "leaflet/dist/leaflet.css";
   9 | import axios from "axios";
  10 | import { useToast } from "@/hooks/use-toast"; {
  digest: '3246626898'
}

this was my page.tsx

"use client";

import React, { useEffect, useRef, useState, useCallback } from "react";
import L from "leaflet";
import "leaflet/dist/leaflet.css";

interface Coords {
  lat: number;
  long: number;
}

const Page: React.FC = () => {
  const [userCoords, setUserCoords] = useState<Coords | null>(null);
  const [status, setStatus] = useState<string>("Initializing location...");
  const mapRef = useRef<L.Map | null>(null);
  const markersLayerRef = useRef<L.LayerGroup | null>(null);
  const markerRef = useRef<L.Marker | null>(null);
  const watchIdRef = useRef<number | null>(null);

  const initializeMap = useCallback((coords: Coords) => {
    // Prevent reinitializing if map already exists
    if (mapRef.current) {
      // Update existing marker or map view
      markerRef.current?.setLatLng([coords.lat, coords.long]);
      mapRef.current.setView([coords.lat, coords.long], 16);
      return;
    }

    // Create map only once
    const map = L.map("map", {
      center: [coords.lat, coords.long],
      zoom: 16,
      zoomControl: true,
      attributionControl: false
    });

    L.tileLayer("https://{s}.tile.openstreetmap./{z}/{x}/{y}.png", {
      attribution: "© OpenStreetMap contributors",
    }).addTo(map);

    // Create marker
    const customIcon = L.icon({
      iconUrl: "https://encrypted-tbn0.gstatic/images?q=tbn:ANd9GcRLWRQ2MP28ucwL3bUexiJ8kfDjKM_IO6TCrw&s",
      iconSize: [40, 40],
      iconAnchor: [20, 40],
      popupAnchor: [0, -40],
    });

    const marker = L.marker([coords.lat, coords.long], { 
      icon: customIcon 
    }).addTo(map);

    // Store references
    mapRef.current = map;
    markerRef.current = marker;
  }, []);

  useEffect(() => {
    // Geolocation tracking
    if ("geolocation" in navigator) {
      watchIdRef.current = navigator.geolocation.watchPosition(
        (position) => {
          const newCoords: Coords = {
            lat: position.coords.latitude,
            long: position.coords.longitude,
          };

          // Minimal state update
          setUserCoords(prevCoords => {
            // Only update if coordinates have changed significantly
            const hasChanged = !prevCoords || 
              Math.abs(newCoords.lat - prevCoords.lat) > 0.0001 ||
              Math.abs(newCoords.long - prevCoords.long) > 0.0001;

            if (hasChanged) {
              initializeMap(newCoords);
              setStatus(`Location: ${newCoords.lat.toFixed(4)}, ${newCoords.long.toFixed(4)}`);
              return newCoords;
            }

            return prevCoords;
          });
        },
        (error) => {
          const errorMessages = {
            [error.PERMISSION_DENIED]: "Location access denied",
            [error.POSITION_UNAVAILABLE]: "Location information unavailable",
            [error.TIMEOUT]: "Location request timed out"
          };
          
          setStatus(`Error: ${errorMessages[error.code] || "Unknown error"}`);
        },
        {
          enableHighAccuracy: true,
          timeout: 10000,
          maximumAge: 0,
        }
      );
    } else {
      setStatus("Geolocation not supported");
    }

    // Cleanup
    return () => {
      if (watchIdRef.current !== null) {
        navigator.geolocation.clearWatch(watchIdRef.current);
      }
      if (mapRef.current) {
        mapRef.current.remove();
      }
    };
  }, [initializeMap]);

  return (
    <div className="w-full bg-white p-6 rounded-lg shadow-lg space-y-4">
      <p className="text-lg font-semibold text-gray-700">{status}</p>
      <div
        id="map"
        className="h-[80vh] w-full rounded-lg shadow-md border border-gray-200"
      />
    </div>
  );
};

export default Page;

I was very confused why this was not getting built. Also even though it ran on the dev mode but still gave me error.

I was not expecting any error as I already used the "use client" on the page.
Hoping the page would be cool and treated as just client side code.

Share Improve this question asked Jan 17 at 20:51 Atul Anand OraonAtul Anand Oraon 4081 gold badge3 silver badges8 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

So I found the answer, with a lot of trial and error and having used the
React.lazy() . It hit me and I just did some wrestling with the bug
and Sheesh folks Here is the solution.

TLDR; Just rename the page.tsx to Leaflet.tsx , nice 89% done let's do 11%

make the new page.tsx in the same dir

"use client";

import dynamic from 'next/dynamic';
const LeafletMap = dynamic(() => import('./Leaflet'), { ssr: false });

export default function Page() {
  return <LeafletMap />;
}

POV: Used ai to smooth my ans.

The dynamic import works for several key reasons:

Why Dynamic Import Works

  1. Client-Side Rendering
  • ssr: false explicitly disables server-side rendering
  • Ensures Leaflet map is only rendered on the client-side
  • Prevents server-side rendering errors with browser-specific APIs like navigator.geolocation
  1. Lazy Loading
  • Components are loaded only when needed
  • Reduces initial bundle size
  • Improves application performance
  1. Next.js Dynamic Import Mechanism
  • next/dynamic uses React's lazy loading under the hood
  • Automatically handles code splitting
  • Provides fallback support during component loading

Technical Details

  • import('./Leaflet') dynamically imports the Leaflet component
  • { ssr: false } tells Next.js to skip server-side rendering
  • Component will only load in the browser
  • Prevents "window is not defined" errors

Best Practice: Use dynamic imports for components with browser-specific APIs or heavy client-side interactions.

发布评论

评论列表(0)

  1. 暂无评论