react-google-maps-api
react-google-maps-api copied to clipboard
Does this support Advanced Markers?
I want to add class names to my marker.
Advanced markers support this: https://developers.google.com/maps/documentation/javascript/advanced-markers/html-markers
But I don't see advanced markers available in the repo.
Can you confirm how can I add class names to my marker?
Thanks!
@JustFly1984 It seems like you're really active here so just wanted to tag for visibility. Thanks.
+1 on this. Bumping up.
Same here ... want to use some other marker clustering lib for big datasets that works better with Advanced Markers but I can't seem to find a way to do it. My main issue is the Map ID during initialization so, +1 from me as well...
So I was able to add Advanced Markers by doing the following:
- When loading @react-google-maps/api, add `libraries: ["marker"]
const { isLoaded } = useJsApiLoader({
googleMapsApiKey: "<redacted>",
libraries: ["marker"],
});
- In my Google Map component, I'm iterating through my locations and rendering custom Marker components:
<GoogleMap
center={center}
zoom={13}
options={options}
mapContainerStyle={{ width: "100%", height: "100%" }}
onLoad={onLoad}
onBoundsChanged={handleBoundsChanged}
>
{mapRef.current &&
locations.map((location) => {
return (
<Marker
key={location.id}
map={mapRef.current}
position={{ lat: location.lat, lng: location.lng }}
>
<div className="marker">
<h2>{location.name}</h2>
</div>
</Marker>
);
})}
</GoogleMap>
Here is the custom Marker component:
"use client";
import { FC, useRef, useEffect } from "react";
import { createRoot, Root } from "react-dom/client";
type LatLngLiteral = google.maps.LatLngLiteral;
type Map = google.maps.Map;
type AdvancedMarkerElement = google.maps.marker.AdvancedMarkerElement;
interface MarkerProps {
map: Map;
position: LatLngLiteral;
children: React.ReactNode;
}
const Marker: FC<MarkerProps> = ({ map, position, children }) => {
const markerRef = useRef<AdvancedMarkerElement>();
const rootRef = useRef<Root>();
useEffect(() => {
if (!rootRef.current) {
const container = document.createElement("div");
rootRef.current = createRoot(container);
markerRef.current = new google.maps.marker.AdvancedMarkerElement({
position,
content: container,
});
}
}, []);
useEffect(() => {
if (!markerRef.current || !rootRef.current) return;
rootRef.current.render(children);
markerRef.current.position = position;
markerRef.current.map = map;
}, [map, position, children]);
return <></>;
};
export default Marker;
This works by essentially translating the jsx/React node (children prop in the above Marker component) into a proper HTML dom element. Tbh I'm not the best at detailing why this works, but I got the insight from this video: https://www.youtube.com/watch?v=8kxYqoY2WwE&t=1019s&ab_channel=GoogleMapsPlatform
"use client" is only next.js compatible
@tcgilbert Your PR is welcome, can you please add this component to the library? I would publish new version.
Hello, I get the following error
I created an ID but I don't know where to put it. Please help.
NOTE: I found the solution here - https://github.com/JustFly1984/react-google-maps-api/issues/3116
@tcgilbert can we get that PR?
I dont want to tag them but with tcgilbert's solution Im getting Illegal constructor for the line new google.maps.marker.AdvancedMarkerElement(...). I'm not using typescript, so there is that change, although I cant currently think of why that itself would matter.
So I was able to add Advanced Markers by doing the following:
- When loading @react-google-maps/api, add `libraries: ["marker"]
const { isLoaded } = useJsApiLoader({ googleMapsApiKey: "<redacted>", libraries: ["marker"], });
- In my Google Map component, I'm iterating through my locations and rendering custom Marker components:
<GoogleMap center={center} zoom={13} options={options} mapContainerStyle={{ width: "100%", height: "100%" }} onLoad={onLoad} onBoundsChanged={handleBoundsChanged} > {mapRef.current && locations.map((location) => { return ( <Marker key={location.id} map={mapRef.current} position={{ lat: location.lat, lng: location.lng }} > <div className="marker"> <h2>{location.name}</h2> </div> </Marker> ); })} </GoogleMap>Here is the custom Marker component:
"use client"; import { FC, useRef, useEffect } from "react"; import { createRoot, Root } from "react-dom/client"; type LatLngLiteral = google.maps.LatLngLiteral; type Map = google.maps.Map; type AdvancedMarkerElement = google.maps.marker.AdvancedMarkerElement; interface MarkerProps { map: Map; position: LatLngLiteral; children: React.ReactNode; } const Marker: FC<MarkerProps> = ({ map, position, children }) => { const markerRef = useRef<AdvancedMarkerElement>(); const rootRef = useRef<Root>(); useEffect(() => { if (!rootRef.current) { const container = document.createElement("div"); rootRef.current = createRoot(container); markerRef.current = new google.maps.marker.AdvancedMarkerElement({ position, content: container, }); } }, []); useEffect(() => { if (!markerRef.current || !rootRef.current) return; rootRef.current.render(children); markerRef.current.position = position; markerRef.current.map = map; }, [map, position, children]); return <></>; }; export default Marker;This works by essentially translating the jsx/React node (children prop in the above Marker component) into a proper HTML dom element. Tbh I'm not the best at detailing why this works, but I got the insight from this video: https://www.youtube.com/watch?v=8kxYqoY2WwE&t=1019s&ab_channel=GoogleMapsPlatform
Heads up, if the mapRef is null when the component mounts, the markers will not show. Given that the ref updating won't trigger a re-render, I needed to create a new state variable (mapLoaded) to replace mapRef.current in the statement that triggers the Markers to show. Once the mapRef is set in the onLoad callback, I set mapLoaded to true.
More actual the need of AdvancedMarker after deprecation warning from Google
Please implement this import
Please implement this import
Which import?
Please implement this import
Which import?
AdvancedMarker
Please implement this import
Which import?
AdvancedMarker
Seems they don't export such component. At which version are you importing that?
Please implement this import
Which import?
AdvancedMarker
Seems they don't export such component. At which version are you importing that?
Right now only Marker is exported but Google has started throwing a warning because it’s depreciated. AdvancedMarker needs to be exported so that it can be used to remove the warning.
Please implement this import
Which import?
AdvancedMarker
Seems they don't export such component. At which version are you importing that?
Right now only Marker is exported but Google has started throwing a warning because it’s depreciated. AdvancedMarker needs to be exported so that it can be used to remove the warning.
I am also here with the same problem :) I thought you already found that the package has exported <AdvancedMarker /> component. So let's wait for the contributors.
@rex-smith Hey! Can you show the code of the Google map and Marker component in full? I don't quite understand what you have changed.
@barabanoveugene
- Here's the marker component
const Marker = ({
map,
position,
children,
onClick,
}: MarkerProps) => {
const markerRef = useRef<AdvancedMarkerElement>();
const rootRef = useRef<Root>();
useEffect(() => {
if (!rootRef.current) {
const container = document.createElement("div");
rootRef.current = createRoot(container);
markerRef.current = new google.maps.marker.AdvancedMarkerElement({
position,
content: container,
});
}
}, [position]);
useEffect(() => {
if (!markerRef.current || !rootRef.current) return;
rootRef.current.render(children);
markerRef.current.position = position;
markerRef.current.map = map;
const clickListener = markerRef.current.addListener("click", onClick);
return () => {
clickListener.remove();
};
}, [map, position, children, onClick]);
return <></>;
};
- Here's the GoogleMap component and onLoad function where the mapRef is initialized. In hindsight, I'm not sure why I didn't just hold the map in state rather than using a ref and keeping "mapLoaded" in state. In the GoogleMap component example, the map is just put into state with setMap(map) instead of mapRef.current = map below. That's how I see it in the example people have been basing this off of too https://github.com/leighhalliday/google-maps-threejs/blob/main/pages/markers.js (although without using the GoogleMap component from this library). In these cases, "map" just replaces "mapLoaded" where I have it below.
const [mapLoaded, setMapLoaded] = useState(false);
const mapRef = useRef<google.maps.Map | null>(null);
const onLoad = useCallback(
(map: google.maps.Map) => {
mapRef.current = map;
setMapLoaded(true);
},
);
<GoogleMap
center={center}
zoom={13}
options={options}
onLoad={onLoad}
>
{mapLoaded &&
locations.map((location) => {
return (
<Marker
key={location.id}
map={mapRef.current}
position={{ lat: location.lat, lng: location.lng }}
>
<div className="marker">
<h2>{location.name}</h2>
</div>
</Marker>
);
})}
</GoogleMap>
@rex-smith can you please make a PR into the package?
@JustFly1984 I just tried, but I can't install the dependencies for some reason
@rex-smith use yarn@1
So implementation is fine, however it is missing many of the events and even will not support the clusters, I am using this package in a medium size project, and now google api started throwing error that, they deprecated the markers.
So AdvancedMarker with cluster and events supports are must have features.
@rex-smith hey, getting the dev setup to work also does not work for me. You could try to make the PR blindly..
If looking to do clusters with AdvancedMarkers, the docs have a useful example: https://developers.google.com/maps/documentation/javascript/marker-clustering
I'm waiting till I get 500$ to my opencollective to implement AdvancedMarker into this library. Currently got 100$. If you guys croudfund this issue, I'll release new version with AdvancedMarker
also found this lib solving most of my problems: https://visgl.github.io/react-google-maps/docs/api-reference/components/advanced-marker
@hassan-mir did you add a component from this library or completely redo the whole project?
@rex-smith Could you share a complete example - of your use of the Marker component using AdvancedMarkerElement?
@alexandermirzoyan you didn't get a fix on the warning?