very new to react. I'm using google-maps-react-api. I have two files. Index.js and MapMarker.js. It loads a few location points with info windows already loaded. I can close the window but when clicking on the marker they do not reopen. My onCLick events do not work as I expect. I want the case to be the markers load and I click them to show info window and then can close the window as well. I've read the docs and issues on Github but can't find the info. Thanks.
Index.js
import ReactDOM from "react-dom";
import React from "react";
import { GoogleMap, LoadScript, MarkerClusterer } from "@react-google-maps/api";
import MapMarker from "./MapMarker";
const mapOptions = {
fullscreenControl: false,
streetViewControl: false,
mapTypeControl: false,
styles: [
{
featureType: "poi",
elementType: "labels",
stylers: [
{
visibility: "off"
}
]
},
{
featureType: "transit",
elementType: "all",
stylers: [
{
visibility: "off"
}
]
}
]
};
const key = ""; // PUT GMAP API KEY HERE
const defaultLocation = {
lat: 37.9755691,
lng: 23.7361789
};
let markers = [
{
id: 1,
lat: 37.975,
lng: 23.7361789
},
{
id: 2,
lat: 37.9755,
lng: 23.7361789
},
{
id: 3,
lat: 37.976,
lng: 23.7361789
}
];
class Map extends React.Component {
state = {
isInfoOpen: false,
selectedMarkerId: null,
noOfClusters: null,
markers: markers
};
onClick = (isInfoOpen, selectedMarkerId) => {
this.setState({
isInfoOpen,
selectedMarkerId
});
};
render() {
const { isInfoOpen, selectedMarkerId } = this.state;
return (
<LoadScript googleMapsApiKey={key} >
<div>
<div
style={{
width: "100%",
height: 500,
display: "flex"
}}
>
<GoogleMap
options={mapOptions}
center={defaultLocation}
zoom={18}
onLoad={this.onMapMounted}
onIdle={this.onMapIdle}
onBoundsChanged={this.onBoundsChanged}
onZoomChanged={this.onZoomChanged}
mapContainerStyle={{ flex: 1 }}
>
<MarkerClusterer averageCenter enableRetinaIcons gridSize={60}>
{clusterer =>
this.state.markers.map(markerData => (
<MapMarker
key={markerData.id}
clusterer={clusterer}
markerData={markerData}
isSelected={markerData.id === selectedMarkerId}
isInfoOpen={
markerData.id === selectedMarkerId && isInfoOpen
}
onClick={() => this.onClick()}
/>
))
}
</MarkerClusterer>
</GoogleMap>
</div>
</div>
</LoadScript>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Map />, rootElement);
MapMarker.js
import React from "react";
import { InfoWindow, Marker} from "@react-google-maps/api";
export default class MapMarker extends React.Component {
state = {
mapMarker: null,
activeMarker: {},
selectedPlace: {},
showingInfoWindow: false
};
onMarkerClick = (props, marker) =>
this.setState({
activeMarker: marker,
selectedPlace: props,
showingInfoWindow: true
});
onInfoWindowClose = () =>
this.setState({
activeMarker: null,
showingInfoWindow: false
});
onLoad = mapMarker => {
this.setState({
mapMarker
});
};
render() {
const { clusterer, markerData } = this.props;
const { mapMarker } = this.state;
return (
<Marker
clusterer={clusterer}
onLoad={this.onLoad}
position={{
lat: markerData.lat,
lng: markerData.lng
}}
onClick={() => this.onMarkerClick()}
>
{mapMarker && (
<InfoWindow
anchor={mapMarker}
position={{
lat: markerData.lat,
lng: markerData.lng
}}
marker={this.state.activeMarker}
onClose={this.onInfoWindowClose}
visible={this.state.showingInfoWindow}
>
<div style={{ background: "white" }}>
{"custom Infobox: " + markerData.id}
</div>
</InfoWindow>
)}
</Marker>
);
}
}
very new to react. I'm using google-maps-react-api. I have two files. Index.js and MapMarker.js. It loads a few location points with info windows already loaded. I can close the window but when clicking on the marker they do not reopen. My onCLick events do not work as I expect. I want the case to be the markers load and I click them to show info window and then can close the window as well. I've read the docs and issues on Github but can't find the info. Thanks.
Index.js
import ReactDOM from "react-dom";
import React from "react";
import { GoogleMap, LoadScript, MarkerClusterer } from "@react-google-maps/api";
import MapMarker from "./MapMarker";
const mapOptions = {
fullscreenControl: false,
streetViewControl: false,
mapTypeControl: false,
styles: [
{
featureType: "poi",
elementType: "labels",
stylers: [
{
visibility: "off"
}
]
},
{
featureType: "transit",
elementType: "all",
stylers: [
{
visibility: "off"
}
]
}
]
};
const key = ""; // PUT GMAP API KEY HERE
const defaultLocation = {
lat: 37.9755691,
lng: 23.7361789
};
let markers = [
{
id: 1,
lat: 37.975,
lng: 23.7361789
},
{
id: 2,
lat: 37.9755,
lng: 23.7361789
},
{
id: 3,
lat: 37.976,
lng: 23.7361789
}
];
class Map extends React.Component {
state = {
isInfoOpen: false,
selectedMarkerId: null,
noOfClusters: null,
markers: markers
};
onClick = (isInfoOpen, selectedMarkerId) => {
this.setState({
isInfoOpen,
selectedMarkerId
});
};
render() {
const { isInfoOpen, selectedMarkerId } = this.state;
return (
<LoadScript googleMapsApiKey={key} >
<div>
<div
style={{
width: "100%",
height: 500,
display: "flex"
}}
>
<GoogleMap
options={mapOptions}
center={defaultLocation}
zoom={18}
onLoad={this.onMapMounted}
onIdle={this.onMapIdle}
onBoundsChanged={this.onBoundsChanged}
onZoomChanged={this.onZoomChanged}
mapContainerStyle={{ flex: 1 }}
>
<MarkerClusterer averageCenter enableRetinaIcons gridSize={60}>
{clusterer =>
this.state.markers.map(markerData => (
<MapMarker
key={markerData.id}
clusterer={clusterer}
markerData={markerData}
isSelected={markerData.id === selectedMarkerId}
isInfoOpen={
markerData.id === selectedMarkerId && isInfoOpen
}
onClick={() => this.onClick()}
/>
))
}
</MarkerClusterer>
</GoogleMap>
</div>
</div>
</LoadScript>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Map />, rootElement);
MapMarker.js
import React from "react";
import { InfoWindow, Marker} from "@react-google-maps/api";
export default class MapMarker extends React.Component {
state = {
mapMarker: null,
activeMarker: {},
selectedPlace: {},
showingInfoWindow: false
};
onMarkerClick = (props, marker) =>
this.setState({
activeMarker: marker,
selectedPlace: props,
showingInfoWindow: true
});
onInfoWindowClose = () =>
this.setState({
activeMarker: null,
showingInfoWindow: false
});
onLoad = mapMarker => {
this.setState({
mapMarker
});
};
render() {
const { clusterer, markerData } = this.props;
const { mapMarker } = this.state;
return (
<Marker
clusterer={clusterer}
onLoad={this.onLoad}
position={{
lat: markerData.lat,
lng: markerData.lng
}}
onClick={() => this.onMarkerClick()}
>
{mapMarker && (
<InfoWindow
anchor={mapMarker}
position={{
lat: markerData.lat,
lng: markerData.lng
}}
marker={this.state.activeMarker}
onClose={this.onInfoWindowClose}
visible={this.state.showingInfoWindow}
>
<div style={{ background: "white" }}>
{"custom Infobox: " + markerData.id}
</div>
</InfoWindow>
)}
</Marker>
);
}
}
Share
Improve this question
asked Jun 14, 2020 at 7:57
RobbenRobben
592 silver badges6 bronze badges
10
- Do you get any errors? What have you tried to debug? Can you provide a working CodeSandbox? – MrUpsidown Commented Jun 14, 2020 at 10:24
- Hey, no errors. I've been reading the documentation and it makes no reference to being able to open and close info windows by clicking markers. react-google-maps-api-docslify.app/#infowindow . I've changed the code a little and here is the sandbox link codesandbox.io/s/cocky-faraday-10kbs?file=/src/index.js . I have a cluster, markers and info boxes displaying permanantly and an alert when the marker is clicked but when I close the info box clicking the marker does not re open. Thanks – Robben Commented Jun 14, 2020 at 11:02
- Do you need multiple info windows to be open at the same time? Otherwise, you should probably use only 1. – MrUpsidown Commented Jun 14, 2020 at 12:04
- No, ideally just one. Click on a marker and one window displays which I can then close and open another one. Thanks so much for your help. – Robben Commented Jun 14, 2020 at 12:08
- 1 That library is google-map-react which doesn’t support marker clustering and the one I’m using google-map-react-api which supports clustering but doesn’t seem to support opening into windows. Thanks again for your help. I might have to Compromise something for now until I can make my own. – Robben Commented Jun 14, 2020 at 12:18
1 Answer
Reset to default 3I made a couple of changes in your MapMaker.js from the codesandbox link you provided.
First, I added a state named showingInfoWindow
and assign a value of false
. This will be the state that will indicate if the infowindow will be shown or not.
Then, I added a function named onMarkerClick
which is called everytime the Marker is clicked. This will set the state of showingInfoWindow
to true
.
Next, I put a condition in the return of MapMaker class, which will only show the infowindow when the showingInfoWindow
is set to true
.
Then, I add the onInfoWindowClose
function that sets the state of showingInfoWindow
back to false
.
Lastly, I added the onCloseClick
parameter in the and call the onInfoWindowClose
function.
You can follow the code snippet below for the changes in MapMaker.js
import React from "react";
import { Marker, InfoWindow } from "@react-google-maps/api";
export default class MapMarker extends React.Component {
state = {
mapMarker: null,
showingInfoWindow: false
};
onMarkerClick = (props) => {
this.setState({
showingInfoWindow: true
});
};
onInfoWindowClose = () =>
this.setState({
showingInfoWindow: false
});
onLoad = (mapMarker) => {
this.setState({
mapMarker
});
};
render() {
const { clusterer, markerData } = this.props;
return (
<Marker
clusterer={clusterer}
onLoad={this.onLoad}
position={{
lat: markerData.lat,
lng: markerData.lng
}}
clickable
onClick={this.onMarkerClick}
>
{this.state.showingInfoWindow === true && (
<InfoWindow
position={{
lat: markerData.lat,
lng: markerData.lng
}}
onCloseClick={this.onInfoWindowClose}
>
<div>
<p>hello</p>
</div>
</InfoWindow>
)}
</Marker>
);
}
}