Added the first constant
const GettingStartedGoogleMap = withGoogleMap(props => (
<GoogleMap
ref={props.onMapLoad}
zoom={13}
center={{ lat: 21.178574, lng: 72.814149 }}
onClick={props.onMapClick}
>
{props.markers.map(marker => (
<Marker
{...marker}
onRightClick={() => props.onMarkerRightClick(marker)}
/>
))}
</GoogleMap>
Changed the containerElement size and mapElement size to pixels instead of percentage
containerElement={
<div style={{ height: `150px` }} />
}
mapElement={
<div style={{ height: `150px` }} />
}
And just adding marker to the function which was called
markers={this.state.markers}
Answer from Dhaval Jardosh on Stack Overflow
» npm install google-maps-react-markers
Videos
Added the first constant
const GettingStartedGoogleMap = withGoogleMap(props => (
<GoogleMap
ref={props.onMapLoad}
zoom={13}
center={{ lat: 21.178574, lng: 72.814149 }}
onClick={props.onMapClick}
>
{props.markers.map(marker => (
<Marker
{...marker}
onRightClick={() => props.onMarkerRightClick(marker)}
/>
))}
</GoogleMap>
Changed the containerElement size and mapElement size to pixels instead of percentage
containerElement={
<div style={{ height: `150px` }} />
}
mapElement={
<div style={{ height: `150px` }} />
}
And just adding marker to the function which was called
markers={this.state.markers}
I'd check over your lat, lng coordinates again. From google explaining coordinates
"Check that the first number in your latitude coordinate is between -90 and 90."
Also any other error info would be helpful getting an answer for you.
Edit:
Since this answer was posted the docs (and likely, the API) of the GoogleMapReact element was changed to support children. Any child with lat and lng would be rendered at the corresponding location on the map, as also indicated by @Jobsamuel's answer.
The onGoogleApiLoaded callback should not be used for this purpose, as it is inferior to the declarative style and would not be re-run if changes are made to the map.
Original answer (outdated):
This may not be entirely clear from the description in the Readme, but the maps argument is, in fact, the maps API object (and map is, of course, the current Google Map instance). Therefore, you should pass both to your method:
onGoogleApiLoaded={({map, maps}) => this.renderMarkers(map, maps)}
and use them:
renderMarkers(map, maps) {
let marker = new maps.Marker({
position: myLatLng,
map,
title: 'Hello World!'
});
}
Adding a marker on your map isn't as easy as we would like to, mostly because the confusing docs but here you have a super easy example:
const Map = props => {
return (
<GoogleMapReact
bootstrapURLKeys={{ props.key }}
defaultCenter={{lat: props.lat, lng: props.lng}}
defaultZoom={props.zoom}>
{/* This is the missing part in docs:
*
* Basically, you only need to add a Child Component that
* takes 'lat' and 'lng' Props. And that Component should
* returns a text, image, super-awesome-pin (aka, your marker).
*
*/}
<Marker lat={props.lat} lng={props.lng}} />
</GoogleMapReact>
)
}
const Marker = props => {
return <div className="SuperAwesomePin"></div>
}
As you can tell, you can pass DOM nodes into advanced markers like you have here:
const markerComponent = document.createElement("div");
markerComponent.innerHTML = `
<img src="${busTopViewImage}" />
<h5 style="background-color: ${markerData.marker.backgroundColor}; color: white; border-radius: 10px; padding: 8px;">
${markerData.marker.text}
</h5>
`;
const m = new AdvancedMarkerElement({
map,
position: markerData.coordinates,
content: markerComponent,
});
The only thing you're missing is to generate the HTML via React.
// Setup a React root on a virtual DOM node
const markerComponent = document.createElement("div");
// Initialize root at new DOM node
const root = ReactDOM.createRoot(el);
// Output HTML into it
root.render(<Marker ... />);
// Use it
const m = new AdvancedMarkerElement({
map,
position: markerData.coordinates,
content: markerComponent,
});
If you need to share state with the rest of the tree, you can combine this with Portals.
You can check this youtube video here: https://www.youtube.com/watch?v=8kxYqoY2WwE
Github source code: https://github.com/leighhalliday/google-maps-threejs/blob/main/pages/markers.js
import { Wrapper } from "@googlemaps/react-wrapper";
import { useRef, useEffect, useState } from "react";
import { createRoot } from "react-dom/client";
export default function App() {
return (
<Wrapper
apiKey={process.env.NEXT_PUBLIC_MAP_API_KEY}
version="beta"
libraries={["marker"]}
>
<MyMap />
</Wrapper>
);
}
const mapOptions = {
mapId: process.env.NEXT_PUBLIC_MAP_ID,
center: { lat: 43.66293, lng: -79.39314 },
zoom: 10,
disableDefaultUI: true,
};
function MyMap() {
const [map, setMap] = useState();
const ref = useRef();
useEffect(() => {
setMap(new window.google.maps.Map(ref.current, mapOptions));
}, []);
return (
<>
<div ref={ref} id="map" />
{map && <Weather map={map} />}
</>
);
}
const weatherData = {
A: {
name: "Toronto",
position: { lat: 43.66293, lng: -79.39314 },
climate: "Raining",
temp: 20,
fiveDay: [15, 18, 12, 22, 20],
},
B: {
name: "Guelph",
position: { lat: 43.544811, lng: -80.248108 },
climate: "Cloudy",
temp: 20,
fiveDay: [15, 18, 12, 22, 20],
},
C: {
name: "Orangeville",
position: { lat: 43.919239, lng: -80.097412 },
climate: "Sunny",
temp: 20,
fiveDay: [15, 18, 12, 22, 20],
},
};
function Weather({ map }) {
const [data, setData] = useState(weatherData);
const [highlight, setHighlight] = useState();
const [editing, setEditing] = useState();
return (
<>
{editing && (
<Editing
weather={data[editing]}
update={(newWeather) => {
setData((existing) => {
return { ...existing, [editing]: { ...newWeather } };
});
}}
close={() => setEditing(null)}
/>
)}
{Object.entries(data).map(([key, weather]) => (
<Marker
key={key}
map={map}
position={weather.position}
onClick={() => setEditing(key)}
>
<div
className={`marker ${weather.climate.toLowerCase()} ${
highlight === key || editing === key ? "highlight" : ""
}`}
onMouseEnter={() => setHighlight(key)}
onMouseLeave={() => setHighlight(null)}
>
<h2>{weather.climate}</h2>
<div>{weather.temp}c</div>
{highlight === key || editing === key ? (
<div className="five-day">
<p>Next 5</p>
<p>{weather.fiveDay.join(", ")}</p>
</div>
) : null}
</div>
</Marker>
))}
</>
);
}
function Editing({ weather, update, close }) {
return (
<div className="editing">
<h2>Editing {weather.name}</h2>
<label htmlFor="climate">Climate</label>
<select
id="climate"
value={weather.climate}
onChange={(e) => update({ ...weather, climate: e.target.value })}
>
{["Sunny", "Cloudy", "Raining"].map((val) => (
<option key={val} value={val}>
{val}
</option>
))}
</select>
<label htmlFor="temp">Temperature</label>
<input
id="temp"
type="number"
value={weather.temp}
onChange={(e) => update({ ...weather, temp: e.target.value })}
/>
<button type="button" onClick={() => close()}>
Close
</button>
</div>
);
}
function Marker({ map, position, children, onClick }) {
const rootRef = useRef();
const markerRef = useRef();
useEffect(() => {
if (!rootRef.current) {
const container = document.createElement("div");
rootRef.current = createRoot(container);
markerRef.current = new google.maps.marker.AdvancedMarkerView({
position,
content: container,
});
}
return () => (markerRef.current.map = null);
}, []);
useEffect(() => {
rootRef.current.render(children);
markerRef.current.position = position;
markerRef.current.map = map;
const listener = markerRef.current.addListener("click", onClick);
return () => listener.remove();
}, [map, position, children, onClick]);
}
for react 18+ you have to import MarkerF instead of Marker and use in it as a tag(of course)
import {MarkerF} from '@react-google-maps/api'
Source
The problem that you're having is something introduced by React 18 related to Strict Mode. If you remove Strict Mode from your app, the markers should appear. That also explains why Smokey Dawson's app worked in production — I'm guessing they removed Strict Mode.
Here's a little documentation about it in a closed issue from the repo: https://github.com/JustFly1984/react-google-maps-api/issues/2978
Hopefully you already resolved this, but if not, I figured I'd answer it since I ran into the same problem this week.