I'm having an issue with rendering google map markers from a state array. Only the last rendered marker is shown although all of the markers are listed in react components
I am using google-maps-react to display a location with many markers representing bookclubs. I fetch the addresses for my markers from a rails API, loop them into a geocoder and set the state within the loop. Each object within the state has the bookclubs lat, lng and data.
I receive the center maps location via form. the data in the form goes through the geocoder and is set to state for the map.
When I add markers using data from state.markers only the last coded marker will show up. This applies when I loop through state.markers or not.
import React, { Component } from "react";
import { Map, InfoWindow, Marker, GoogleApiWrapper } from "google-maps-react";
class GoogleMaps extends Component {
constructor(props) {
super(props);
this.state = {
markers: [],
lat: null,
lng: null,
showingInfoWindow: false,
activeMarker: {},
selectedPlace: {}
};
}
componentDidMount() {
fetch("RAILS API ROUTE", {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + sessionStorage.JWT
}
})
.then(e => e.json())
.then(data => {
let bookClubs = data.book_clubs;
console.log("let", bookClubs);
bookClubs.forEach(club => {
const googleMapsClient = require("@google/maps").createClient({
key: "API KEY",
Promise: Promise
});
googleMapsClient
.geocode({
address: `${(club.address.address_line1,
club.address.address_line2,
club.address.city)}`
})
.asPromise()
.then(response => {
console.log("response!!!!!!!!!!!!!", response.json.results);
let info = {
lat: response.json.results[0].geometry.location.lat,
lng: response.json.results[0].geometry.location.lng,
bookClub: club
};
let dataCopy = this.state.markers
dataCopy.push(info);
this.setState(
{
markers: dataCopy
},
() => {
console.log("State::::", this.state.markers);
}
);
});
});
})
.catch(error => console.error("Error:", error));
}
onMarkerClick = (props, marker, e) =>
this.setState({
selectedPlace: props,
activeMarker: marker,
showingInfoWindow: true
});
onMapClicked = props => {
if (this.state.showingInfoWindow) {
this.setState({
showingInfoWindow: false,
activeMarker: null
});
}
};
render() {
return (
<div
style={{ display: "flex", flexDirection: "flexEnd", flexWrap: "wrap" }}
>
{this.state.lat != null && (
<Map
onClick={this.onMapClick}
google={this.props.google}
initialCenter={{
lng: this.state.lng,
lat: this.state.lat
}}
center={{
lng: this.state.lng,
lat: this.state.lat
}}
containerStyle={{
width: "100%",
height: "250px",
position: "relative"
}}
style={{
height: "35vh",
width: "35vh",
display: "flex",
justifyContent: "flexEnd"
}}
zoom={14}
>
{this.state.markers.map((e, i) => (
<Marker
key={i}
onClick={this.onMarkerClick}
position={{ lat: e.lat, lng: e.lng }}
title={`${e.bookClub.address.address_line1} ${e.bookClub.address.address_line2}`}
name={e.bookClub.address.city}
/>
))}
<InfoWindow
marker={this.state.activeMarker}
visible={this.state.showingInfoWindow}
>
<div>
<h1>{this.state.selectedPlace.name}</h1>
</div>
</InfoWindow>
</Map>
)
}
</div>
);
}
}
export default GoogleApiWrapper({
apiKey: "API KEY"
})(GoogleMaps);
The problem was that I was adding commas while inserting data into my geocoder.
googleMapsClient
.geocode({
address: `${(club.address.address_line1,
club.address.address_line2,
club.address.city)}
I removed the commas and made the code like below, which solved my problem.
googleMapsClient
.geocode({
address: `${club.address.address_line1} ${club.address.address_line2} ${club.address.city} `
})
The reason only the last marker showed is that the geocoder gave all the markers the same lat and lng when I had commas. This caused all of them to cover each other in the same location while the last rendered marker was left on top.