Reputation: 41
The Google Maps API library I am using for this is https://github.com/JustFly1984/react-google-maps-api
What I have been asked to create is a map with multiple markers, each of which can be clicked on to open an InfoWindow centred on that marker. Much like the AirBnB search page, with the map on one side results on the other.
However, I seem to only be able to have an InfoWindow that is open at the loading of the page and then can't be opened again.
My research so far has generally shown that I would need to completely redo this component as a class instead. Although I don't really understand the class based model of components, so ideally I wouldn't have to mess around with that.
Is there a way to make the desired effect without reworking my program entirely?
This is the code for the component, in case it is relevant
import styles from '../../styles/Home.module.css';
import { Marker, LoadScriptNext, GoogleMap, InfoWindow } from '@react-google-maps/api';
import { Fragment, React } from 'react';
import { Typography } from '@material-ui/core';
export default function MapPanel(props) {
return (
<Fragment>
<LoadScriptNext id='google-map-example' googleMapsApiKey="MYAPIKEY">
<GoogleMap mapContainerStyle={{ width: "100%", height: "800px" }}
id='google-map'
center={props.centre}
heading="0"
zoom={12}>
{addMarkers(props.markerList)}
</GoogleMap>
</LoadScriptNext>
</Fragment>
);
}
function addMarkers(markerList) {
if (markerList != undefined) {
return (markerList.map((marker, index) => makeMarker(marker, index)))
}
}
function makeMarker(marker, index) {
const handleClick = () => {
console.log(`${marker.title} marker clicked`);
}
return (
<Marker id={index} position={marker.latLong} title={marker.title} onClick={handleClick}>
<InfoWindow id='Test' position={marker.latLong}>
<Typography variant='body2'>{marker.text}</Typography>
</InfoWindow>
</Marker>
);
}
Upvotes: 0
Views: 948
Reputation: 768
To achieve your goal you would want to use states in your application. But since you want to deal with it using Function components, you would need to make use of react hooks to use states.
Here is a working sample for your reference: https://stackblitz.com/edit/marker-with-infowindow-react-api-o6357y
import ReactDOM from "react-dom";
import React from "react";
import {
GoogleMap,
Marker,
InfoWindow,
LoadScript
} from "@react-google-maps/api";
import data from "./data.json";
const { useState } = React;
const containerStyle = {
width: "400px",
height: "400px"
};
const center = { lat: 40.712775, lng: -74.005973 };
function Map() {
const [infoWindowID, setInfoWindowID] = useState("");
let markers;
if (data !== null) {
markers = data.map((location, i) => {
const marker = { lat: location.lat, lng: location.lng };
const index = i + 1;
return (
<Marker
key={index}
position={marker}
label={index.toString()}
onClick={() => {
setInfoWindowID(index);
}}
>
{infoWindowID === index && (
<InfoWindow>
<span>Something {index}</span>
</InfoWindow>
)}
</Marker>
);
});
}
return (
<LoadScript googleMapsApiKey="YOUR_API_KEY">
<GoogleMap mapContainerStyle={containerStyle} center={center} zoom={10}>
{markers}
</GoogleMap>
</LoadScript>
);
}
export default React.memo(Map);
Upvotes: 1