-
I'm using Next.js, already converted all page using Client Component, while also importing all dependent children component to force disable SSR. My page just contains the maps component, custom map control component, and several hooks for managing the state of maps. Is there any special pattern while using this plugin on Next.js project? Thanks in advance for any help🙏🏻 Here's my page: "use client";
import { LoaderComponent } from "@/components/loader";
import { useDrawingGoogleMaps } from "@/hooks/google-maps/drawing";
import { useInfoWindowGoogleMaps } from "@/hooks/google-maps/infowindow";
import { useMarkerGoogleMaps } from "@/hooks/google-maps/marker";
import { usePlaceGoogleMaps } from "@/hooks/google-maps/place";
import { usePosition } from "@/hooks/google-maps/position";
import { DEFAULT_POSITION, DEFAULT_ZOOM, getCurrentLocation, getFormattedAddress } from "@/lib/maps";
import { ControlPosition, Map as GoogleMap, MapControl, useMap } from "@vis.gl/react-google-maps";
import dynamic from "next/dynamic";
import { Suspense, useEffect } from "react";
const MapControlPlaceSearch = dynamic(() => import("@/components/maps/map-control/place-search"), { ssr: false });
const MapControlCurrentLocation = dynamic(() => import("@/components/maps/map-control/current-location"), {
ssr: false,
});
const MapControlDraw = dynamic(() => import("@/components/maps/map-control/draw"), {
ssr: false,
});
const MapControlZoom = dynamic(() => import("@/components/maps/map-control/zoom"), {
ssr: false,
});
const MarkerWithInfoWindow = dynamic(() => import("@/components/maps/marker-with-infowindow"), { ssr: false });
// FIXME: bug when the map is loaded, sometimes the map is blank.
// There is error in the console "Internal error: ReferenceError: document is not defined"
// I think is caused by the library "@vis.gl/react-google-maps" on Next.js server side rendering.
// const MapsPage = () => {
export default function MapsPage() {
const map = useMap();
const { currentPosition, setCurrentPosition, setMarkerPosition, markerPosition } = usePosition();
const { infoWindowService, setInfoWindowOpen: setInfoWindowOpenIW } = useInfoWindowGoogleMaps();
const { markerRef, infoWindowOpen, marker, infoWindowDescription, setInfoWindowOpen, setInfoWindowDescription } =
useMarkerGoogleMaps();
const { handlingUndoOverlay, handleToggleDrawingMode, drawingMode, selectedOverlay } = useDrawingGoogleMaps({
infoWindowService,
setInfoWindowOpen: setInfoWindowOpenIW,
});
const { pacInputRef, savedAddress } = usePlaceGoogleMaps({
setCurrentPosition,
setMarkerPosition,
setInfoWindowOpen,
setInfoWindowDescription,
});
/**
* Initialize current location
*/
async function initCurrentLocation() {
try {
console.info("current position before", currentPosition);
const { lat, lng } = await getCurrentLocation();
console.info("current position after", { lat, lng });
setCurrentPosition({ lat, lng });
setMarkerPosition({ lat, lng });
} catch (error) {
setCurrentPosition(DEFAULT_POSITION);
setMarkerPosition(DEFAULT_POSITION);
}
}
// * Module Marker
async function initCurrentPositionMarker(position: google.maps.LatLngLiteral) {
const formattedAddress = (await getFormattedAddress({ lat: position.lat, lng: position.lng })) ?? "";
setInfoWindowDescription(formattedAddress);
setInfoWindowOpen(true);
savedAddress.current = formattedAddress;
console.info(
{
lat: position.lat,
lng: position.lng,
address: formattedAddress,
},
"Here is the marker position",
);
}
async function handlingMarkerDragEnd(e: google.maps.MapMouseEvent) {
const position = e.latLng;
if (position) {
const formattedAddress = (await getFormattedAddress({ lat: position.lat(), lng: position.lng() })) ?? "";
setInfoWindowDescription(formattedAddress);
setInfoWindowOpen(true);
savedAddress.current = formattedAddress;
console.info(
{
lat: position.lat(),
lng: position.lng(),
address: formattedAddress,
},
"Here is the marker position",
);
}
}
useEffect(() => {
initCurrentLocation();
}, []);
useEffect(() => {
if (!map || !currentPosition) return;
initCurrentPositionMarker(currentPosition);
console.log(currentPosition, "changed current position", "page.tsx");
}, [currentPosition, map]);
return (
// Height is calculated by subtracting the height of the header
<div className="w-full h-[calc(100vh-4rem)] gap-4 md:gap-8">
<GoogleMap
mapId={process.env.NEXT_PUBLIC_GOOGLE_MAPS_MAP_API_XURYA_CALCULATOR ?? ""}
defaultCenter={currentPosition ?? DEFAULT_POSITION}
defaultZoom={DEFAULT_ZOOM}
reuseMaps
disableDefaultUI
mapTypeId="hybrid"
className="map-container w-full h-full overflow-hidden"
/>
<MarkerWithInfoWindow
markerTitle="Your Location"
markerPosition={markerPosition}
markerRef={markerRef}
handlingMarkerDragEnd={handlingMarkerDragEnd}
infoWindowOpen={infoWindowOpen}
marker={marker}
infoWindowDescription={infoWindowDescription}
/>
<MapControl position={ControlPosition.TOP_CENTER}>
<div className="flex flex-col justify-center items-center">
<MapControlPlaceSearch pacInputRef={pacInputRef} savedAddress={savedAddress} />
<div className="flex justify-center items-center gap-x-4">
<MapControlZoom />
<MapControlDraw
handlingUndoOverlay={handlingUndoOverlay}
handleToggleDrawingMode={handleToggleDrawingMode}
drawingMode={drawingMode}
selectedOverlay={selectedOverlay}
/>
<MapControlCurrentLocation initCurrentLocation={initCurrentLocation} position={currentPosition} />
</div>
</div>
</MapControl>
</div>
);
}
// export default dynamic(() => Promise.resolve(MapsPage), { ssr: false }); |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
Oh, I forget to add, that Maps is also functional if I'm just dragging on the Maps (The greyed Blank container) then it will be show the maps properly. So I think it's just something error during starting rendering a page. nextjs.issue.react.google.maps.mp4 |
Beta Was this translation helpful? Give feedback.
So far, after I'm toggling all of them, the big differences are when to toggle the
mapTypeId
. When using defaultmapTypeId
, it shows properly by showing maps on default center config. I think it's like the maps is failing to fetch the data needed for initial screen when set it tohybrid
.