How do I get my route to show up on my map with React Google Maps? - undefined

I've successfully been able to render the Markers for react-google-maps, but when I started trying to use DirectionsRenderer, I ran into this 'google is not defined' issue. I scoured StackOverflow and the web in general for solutions to this, anywhere from declaring 'google' as a global to playing around with the withScriptjs syntax, and nothing has worked. I'm running out of ideas. Sidenote: I'm deliberately avoiding using the 'recompose' library from the docs because even the library's author thinks Hooks are better...so idk, maybe give me a solution that doesn't require 'recompose' if possible? Thanks a million.
Here's my code:
/* global google */
import React, { useState, useEffect } from 'react'
import { withGoogleMap, GoogleMap, Marker, DirectionsRenderer } from 'react-google-maps'
import './App.css'
function MyDirectionsRenderer(props) {
const [directions, setDirections] = useState(null);
const { origin, destination, travelMode } = props;
useEffect(() => {
const directionsService = new google.maps.DirectionsService();
directionsService.route(
{
origin: new google.maps.LatLng(origin.lat, origin.lng),
destination: new google.maps.LatLng(destination.lat, destination.lng),
travelMode: travelMode
},
(result, status) => {
if (status === google.maps.DirectionsStatus.OK) {
setDirections(result);
} else {
console.error(`error fetching directions ${result}`);
}
}
);
}, [directions, destination.lat, destination.lng, origin.lat, origin.lng, travelMode]);
return (
<React.Fragment>
{directions && <DirectionsRenderer directions={directions} />}
</React.Fragment>
);
}
class Map extends React.Component {
constructor(props){
super(props);
this.state = {
directions: null
}
}
render(){
const MyMapComponent = withGoogleMap(props => {
return (
<GoogleMap
defaultZoom={10}
defaultCenter={{ lat: 42.681340, lng: -89.026930 }}
>
<Marker
position = {{lat: 42.681340, lng: -89.026930}}
/>
<MyDirectionsRenderer
origin= {{lat: 42.681339, lng: -89.026932}}
destination= {{lat: 28.250200, lng: -82.714080}}
travelMode= {google.maps.TravelMode.DRIVING}
/>
</GoogleMap>
)
})
return (
<MyMapComponent
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
)
}
}
export default Map
Edit: I updated the code here to reflect the current status of the project and any existing problems with it. Currently, the problem is that I can't see the route on my map.

Since ESLint is not aware that the variable google is a global, you can declare a variable you referenced as a global by adding the following to the top of your file:
/* global google */
then the error 'google' is not defined should disappear.
And last but not least, the instance of google.maps.DirectionsService could be created only once the Google Maps APIs is loaded. The following example demonstrates how to accomplish it:
<GoogleMap
defaultZoom={4}
defaultCenter={{ lat: 27.71415, lng: -82.3583 }}
>
<MyDirectionsRenderer
origin={{ lat: 27.71415, lng: -82.3583 }}
destination={{ lat: 42.681339, lng: -89.026932 }}
travelMode={google.maps.TravelMode.DRIVING}
/>
</GoogleMap>
where
function MyDirectionsRenderer(props) {
const [directions, setDirections] = useState(null);
const { origin, destination, travelMode } = props;
useEffect(() => {
const directionsService = new google.maps.DirectionsService();
directionsService.route(
{
origin: new google.maps.LatLng(origin.lat, origin.lng),
destination: new google.maps.LatLng(destination.lat, destination.lng),
travelMode: travelMode
},
(result, status) => {
if (status === google.maps.DirectionsStatus.OK) {
setDirections(result);
} else {
console.error(`error fetching directions ${result}`);
}
}
);
}, [directions]);
return (
<React.Fragment>
{directions && <DirectionsRenderer directions={directions} />}
</React.Fragment>
);
}

Related

Google Maps API, Marker onClick listener not working as intended

right now I'm trying to build a map that shows all the hospitals in Indonesia (and later on about covid cases) and so far I've been able to successfully grab locations from a json file and map it onto a map. My map has a button such that if you click it all the hospitals in Indonesia will show up on the map as markers. What I want to do now is to have an InfoWindow pop-up of the hospital name when a user clicks on a specific marker.
How I tried to approach it:
Create a state boolean array for all hospital markers to see if the hospital has been clicked
If the hospital has been clicked, output an InfoWindow with the Hospitals name.
Issue:
It seems that when I click the button to show all hospitals in Indonesia, it updates the state boolean array to all true. I'm not sure why that is the case, and when I click on a specific marker the state array is unchanged.
This is my git repo if you need the full code: https://github.com/ktanojo17505/google-map-react
Here is my state:
state = {
address: "",
city: "",
area: "",
state: "",
zoom: 11,
height: 400,
mapPosition: {
lat: 0,
lng: 0
},
markerPosition: {
lat: 0,
lng: 0
},
placeHospitals: false,
Hospitals: [],
didClickHospital: []
};
This is my constructor:
constructor(props) {
super(props);
var HospitalLocations = [];
var clickHospital = [];
var position;
var hospitalName;
var id;
for (let index = 0; index < HospitalData.hospitals.length; ++index) {
id = index;
var latitude = HospitalData.hospitals[index].latitude;
var longitude = HospitalData.hospitals[index].longitude;
position = { latitude, longitude };
hospitalName = HospitalData.hospitals[index].nama;
var entry = { id, position, hospitalName };
HospitalLocations.push(entry);
clickHospital.push(false);
}
this.state.Hospitals = HospitalLocations;
this.state.didClickHospital = clickHospital;
}
This is my return
return (
<div style={{ padding: "1rem", margin: "0 auto", maxWidth: 1000 }}>
<h1>Google Maps Basic</h1>
<Descriptions bordered>
<Descriptions.Item label="City">{this.state.city}</Descriptions.Item>
<Descriptions.Item label="Area">{this.state.area}</Descriptions.Item>
<Descriptions.Item label="State">
{this.state.state}
</Descriptions.Item>
<Descriptions.Item label="Address">
{this.state.address}
</Descriptions.Item>
</Descriptions>
<MapWithAMarker
googleMapURL={
"https://maps.googleapis.com/maps/api/js?key=" +
config.GOOGLE_API_KEY +
"&v=3.exp&libraries=geometry,drawing,places"
}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
<div style={{ marginTop: "2.5rem" }}>
<Button onClick={this.placeHospitals}>Hospitals</Button>
</div>
</div>
);
MapwithMarker
const MapWithAMarker = withScriptjs(
withGoogleMap(props => (
<div>
<GoogleMap
defaultZoom={this.state.zoom}
defaultCenter={{
lat: this.state.mapPosition.lat,
lng: this.state.mapPosition.lng
}}
options={options}
onClick={this.placeMarker}
>
<Marker
draggable={true}
onDragEnd={this.onMarkerDragEnd}
position={{
lat: this.state.markerPosition.lat,
lng: this.state.markerPosition.lng
}}
>
<InfoWindow>
<div>{this.state.address}</div>
</InfoWindow>
</Marker>
{this.state.placeHospitals &&
this.state.Hospitals.map(hospitalLoc => ( // Place the locations if Hospitals Button is clicked
<Marker
draggable={false}
position={{
lat: hospitalLoc.position.latitude,
lng: hospitalLoc.position.longitude
}}
key={hospitalLoc.id}
onClick={this.clickHospital(hospitalLoc.id)} // Change the state of the Hospital InfoWindow
>
{/* {this.state.didClickHospital[index] && ( // If true output an infowindow of the hospital name
<InfoWindow>
<div>{hospitalLoc.name}</div>
</InfoWindow>
)} */}
</Marker>
))}
<AutoComplete
style={{
width: "100%",
height: "40px",
paddingLeft: 16,
marginTop: 2,
marginBottom: "2rem"
}}
types={["(regions)"]}
onPlaceSelected={this.onPlaceSelected}
/>
</GoogleMap>
</div>
))
);
clickHospital
clickHospital = id => {
console.log("clicked");
// var tempClickHospital = this.state.didClickHospital;
// console.log(tempClickHospital[index]);
// tempClickHospital[index] = !tempClickHospital[index];
// console.log(tempClickHospital[index]);
// this.setState({ didClickHospital: tempClickHospital });
// console.log(this.state.didClickHospital);
};
This is the output of my code (before clicking Hospitals)1
This is the output of my code (after clicking Hospitals)2
If anyone could point out what I'm doing wrong that would be helpful thank you!
You can directly map each data from the json file to create an individual <Marker> with <InfoWindow> inside it.
Here's a working sample code and the code snippet below on how to do this:
import React, { Component } from "react";
import {
withGoogleMap,
GoogleMap,
Marker,
InfoWindow
} from "react-google-maps";
//import the json data of your hospital info
import data from "./data.json";
import "./style.css";
class Map extends Component {
constructor(props) {
super(props);
this.state = {
hospitalId: "",
addMarkerBtn: false
};
}
addMarkerFunction = () => {
this.setState({
addMarkerBtn: true
});
};
handleToggleOpen = id => {
this.setState({
hospitalId: id
});
};
render() {
const GoogleMapExample = withGoogleMap(props => (
<GoogleMap
defaultCenter={{ lat: -6.208763, lng: 106.845599 }}
defaultZoom={16}
>
{this.state.addMarkerBtn === true &&
data.map(hospital => (
<Marker
key={hospital.id}
position={{ lat: hospital.lat, lng: hospital.lng }}
onClick={() => this.handleToggleOpen(hospital.id)}
>
{this.state.hospitalId === hospital.id && (
<InfoWindow
onCloseClick={this.props.handleCloseCall}
options={{ maxWidth: 100 }}
>
<span>{hospital.id}</span>
</InfoWindow>
)}
</Marker>
))}
</GoogleMap>
));
return (
<div>
<button id="addMarker" onClick={() => this.addMarkerFunction()}>
Add Marker
</button>
<GoogleMapExample
containerElement={<div style={{ height: `500px`, width: "500px" }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
}
export default Map;

Maps blank react native

I'm having a problem while viewing google maps in my react native app. I ran a test with an HTML file and it displays. But in my app open blank but shows the logo of google. Below my map code.
App.js
import React, { Component, Fragment } from 'react';
import { View, Image } from 'react-native';
import MapView, { Marker } from 'react-native-maps';
import Geocoder from 'react-native-geocoding';
import { getPixelSize } from '../../components/utils';
import Search from '../Search';
import Directions from '../Directions';
import Details from '../Details';
import markerImage from '../../assets/marker.png';
import backImage from '../../assets/back.png';
import {
Back,
LocationBox,
LocationText,
LocationTimeBox,
LocationTimeText,
LocationTimeTextSmall
} from './styles';
Geocoder.init('MY API');
export default class Map extends Component {
state = {
region: null,
destination: null,
duration: null,
location: null
};
async componentDidMount () {
navigator.geolocation.getCurrentPosition(
async ({ coords: { latitude, longitude } }) => {
const response = await Geocoder.from({ latitude, longitude });
const address = response.results[0].formatted_address;
const location = address.substring(0, address.indexOf(','));
console.log(latitude);
console.log(longitude);
this.setState({
location,
region: {
latitude,
longitude,
latitudeDelta: 0.0143,
longitudeDelta: 0.0134
}
});
}, // sucesso
() => {}, // erro
{
timeout: 2000,
enableHighAccuracy: true,
maximumAge: 1000
}
);
}
handleLocationSelected = (data, { geometry }) => {
const {
location: { lat: latitude, lng: longitude }
} = geometry;
this.setState({
destination: {
latitude,
longitude,
title: data.structured_formatting.main_text
}
});
};
handleBack = () => {
this.setState({ destination: null });
};
render () {
const { region, destination, duration, location } = this.state;
return (
<View style={{ flex: 1 }}>
<MapView
style={{ flex: 1 }}
region={region}
showsUserLocation
loadingEnabled
ref={el => (this.mapView = el)}
>
{destination && (
<Fragment>
<Directions
origin={region}
destination={destination}
onReady={result => {
this.setState({ duration: Math.floor(result.duration) });
this.mapView.fitToCoordinates(result.coordinates, {
edgePadding: {
right: getPixelSize(50),
left: getPixelSize(50),
top: getPixelSize(50),
bottom: getPixelSize(350)
}
});
}}
/>
<Marker
coordinate={destination}
anchor={{ x: 0, y: 0 }}
image={markerImage}
>
<LocationBox>
<LocationText>{destination.title}</LocationText>
</LocationBox>
</Marker>
<Marker coordinate={region} anchor={{ x: 0, y: 0 }}>
<LocationBox>
<LocationTimeBox>
<LocationTimeText>{duration}</LocationTimeText>
<LocationTimeTextSmall>MIN</LocationTimeTextSmall>
</LocationTimeBox>
<LocationText>{location}</LocationText>
</LocationBox>
</Marker>
</Fragment>
)}
</MapView>
{destination ? (
<Fragment>
<Back onPress={this.handleBack}>
<Image source={backImage} />
</Back>
<Details />
</Fragment>
) : (
<Search onLocationSelected={this.handleLocationSelected} />
)}
</View>
);
}
}
In androidManifest i put the correct code and the rest also, I do not know what else to do , I think it might be something with my emulator, can anyone give me a guideline?
you need to install google play services or Gapps on emulator.

How to create Polyline using react-google-maps library

I am trying to plot Polyline between 4 GPS coordinates using react-google-maps library. Nothing is rendering on the map
import React from 'react';
import { withGoogleMap, GoogleMap, Marker, InfoWindow,Polyline } from 'react-google-maps';
class googleMapComponent extends React.Component {
//Higher order components: withGoogleMap is employed as a function call. This fucntion returns another component defination which is later mounted in render
// maintain a refernce to a map inside the component, so that
constructor(){
super()
this.state ={
map:null
}
}
mapMoved(){
console.log('mapMoved: ' + JSON.stringify(this.state.map.getCenter()))
}
mapLoaded(map){
//console.log('mapLoaded: ' + JSON.stringify(map.getCenter()))
if(this.state.map !==null)
return
this.setState({
map:map
})
}
zoomchanged(){
console.log('mapZoomed: ' + JSON.stringify(this.state.map.getZoom()))
}
handleMarkerClick(targetMarker) {
this.setState({
markers: this.state.markers.map(marker => {
if (marker === targetMarker) {
return {
...marker,
showInfo: true,
};
}
return marker;
}),
});
}
handleMarkerClose(targetMarker) {
this.setState({
markers: this.state.markers.map(marker => {
if (marker === targetMarker) {
return {
...marker,
showInfo: false,
};
}
return marker;
}),
});
}
render() {
const markers= [
{
position: new google.maps.LatLng(36.05298766, -112.0837566),
showInfo: false,
infoContent: false,
},
{
position: new google.maps.LatLng(36.21698848, -112.0567275),
showInfo: false,
infoContent: false,
},
]
const lineCoordinates= [
{coordinate: new google.maps.LatLng(36.05298766, -112.0837566)},
{coordinate: new google.maps.LatLng(36.0529832169413, -112.083731889724)},
{coordinate: new google.maps.LatLng(36.0529811214655, -112.083720741793)},
{coordinate: new google.maps.LatLng(36.0529811214655, -112.083720741793)},
]
return (
<GoogleMap
ref={this.mapLoaded.bind(this)}
onDragEnd={this.mapMoved.bind(this)}
onZoomChanged={this.zoomchanged.bind(this)}
defaultZoom={this.props.zoom}
defaultCenter={this.props.center}
>
{markers.map((marker, index) => (
<Marker
position={marker.position}
title="click on it Sir..!!"
defaultPosition={this.props.center}
style={{height: '2xpx', width: '2px'}}
/>
))}
{lineCoordinates.map((polyline,index)=>(
<Polyline
defaultPosition={this.props.center}
path= {polyline.coordinate}
geodesic= {true}
strokeColor= {#FF0000}
strokeOpacity= {1.0}
strokeWeight= {2}
/>
</GoogleMap>
)
}
}
export default withGoogleMap(googleMapComponent);
Any suggestion on it will be helpful. If the library does not support this functionality. I can swtich the library too.
Yes. Example:
render() {
const pathCoordinates = [
{ lat: 36.05298765935, lng: -112.083756616339 },
{ lat: 36.2169884797185, lng: -112.056727493181 }
];
return (
<GoogleMap
defaultZoom={this.props.zoom}
defaultCenter={this.props.center}
>
{/*for creating path with the updated coordinates*/}
<Polyline
path={pathCoordinates}
geodesic={true}
options={{
strokeColor: "#ff2527",
strokeOpacity: 0.75,
strokeWeight: 2,
icons: [
{
icon: lineSymbol,
offset: "0",
repeat: "20px"
}
]
}}
/>
</GoogleMap>
);
}
When you run the mapping function, are you creating a new polyline for each set of coordinates? Looking at the Google Maps docs, the polyline takes an array of objects as a path argument. google-maps-react is just a wrapper around that API, so you should be able to create your polyline just by passing in the array of objects as the path. Currently, you're trying to generate a bunch of polyline objects based on tiny coordinate fragments.
A simpler example to show just one polyline being drawn:
<GoogleMap defaultZoom={7} defaultCenter={{ lat: -34.897, lng: 151.144 }}>
<Polyline path={[{ lat: -34.397, lng: 150.644 }, { lat: -35.397, lng: 151.644 }]}/>
</GoogleMap>
Entire snippet for anyone unclear about the correct imports and setup (with recompose):
import React from "react";
import ReactDOM from "react-dom";
import { compose, withProps } from "recompose";
import {
withScriptjs,
withGoogleMap,
GoogleMap,
Marker,
Polyline
} from "react-google-maps";
const MyMapComponent = compose(
withProps({
googleMapURL:
"https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&v=3.exp&libraries=geometry,drawing,places",
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px` }} />,
mapElement: <div style={{ height: `100%` }} />
}),
withScriptjs,
withGoogleMap
)(props => (
<GoogleMap defaultZoom={7} defaultCenter={{ lat: -34.897, lng: 151.144 }}>
<Polyline path={[{ lat: -34.397, lng: 150.644 }, { lat: -35.397, lng: 151.644 }]}/>
</GoogleMap>
));
ReactDOM.render(<MyMapComponent />, document.getElementById("root"));
Same example as above, without recompose:
import React from "react";
import ReactDOM from "react-dom";
import {
withScriptjs,
withGoogleMap,
GoogleMap,
Polyline
} from "react-google-maps";
const InternalMap = props => (
<GoogleMap defaultZoom={7} defaultCenter={{ lat: -34.897, lng: 151.144 }}>
<Polyline
path={[{ lat: -34.397, lng: 150.644 }, { lat: -35.397, lng: 151.644 }]}
/>
</GoogleMap>
);
const MapHoc = withScriptjs(withGoogleMap(InternalMap));
const MyMapComponent = props => (
<MapHoc
googleMapURL="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&v=3.exp&libraries=geometry,drawing,places"
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
);
ReactDOM.render(
<MyMapComponent />,
document.getElementById("root")
);

React-google-maps +redux - how to center map when new location is fetched?

I am using react-google-maps and I followed that example : LINK . I am fetchng data which comes from GPS device and I would like to center when new data is fetched.
Here is code of the whole map component:
const GettingStartedGoogleMap = withGoogleMap(props => (
<GoogleMap
ref={props.onMapLoad}
defaultZoom={18}
defaultCenter={props.defCenter}
onClick={props.onMapClick}
>
{props.markers.map((marker,i) => (
<Marker
key={i}
position={marker.location}
time={marker.time}
onClick={() => props.onMarkerClick(marker)}
>
{ marker.isShown &&
<InfoWindow onCloseClick={() => props.onMarkerClick(marker)}>
<div className="marker-text">{marker.time} </div>
</InfoWindow>
}
</Marker>
))}
</GoogleMap>
));
class GettingStartedExample extends Component {
componentDidMount(){
this.props.fetchMarkers();
console.log("MONT");
console.log(this.props.markers.length);
}
componentWillReceiveProps(){
console.log(this.props.markers);
console.log(this.props.markers.length);
}
state = {
markers: this.props.markers,
center: {lat: 50.07074, lng: 19.915718},
};
handleMapLoad = this.handleMapLoad.bind(this);
handleMarkerClick = this.handleMarkerClick.bind(this);
handleMapLoad(map) {
this._mapComponent = map;
if (map) {
console.log(map.getZoom());
}
}
handleMarkerClick(targetMarker) {
/*
* All you modify is data, and the view is driven by data.
* This is so called data-driven-development. (And yes, it's now in
* web front end and even with google maps API.)
*/
const nextMarkers = this.state.markers.filter(marker => marker !== targetMarker);
if(targetMarker.isShown==true)
{
targetMarker.isShown=false;
}
else
{
targetMarker.isShown=true;
}
this.setState({
markers: nextMarkers,
center: {lat: 5.07074, lng: 19.915718}
});
}
render() {
const markers = this.props.markers.map((marker,i) => {
return (
<Marker key={i} position={marker.location} time={marker.time} onClick={this.handleMarkerClick} />
)});
var centerPos;
var lastMark;
if(markers[markers.length-1]!== undefined)
{
centerPos=markers[markers.length-1].props.position;
lastMark=markers[markers.length-1].props;
console.log(centerPos);
}
else {
centerPos={lat: 5.07074, lng: 19.915718};
}
return (
<div className='container map-container'>
<GettingStartedGoogleMap
containerElement={
<div style={{ height: `100%` }} />
}
mapElement={
<div style={{ height: `100%` }} />
}
onMapLoad={this.handleMapLoad}
markers={this.props.markers}
onMarkerClick={this.handleMarkerClick}
defCenter={this.state.center}
lastMarker={lastMark}
/>
</div>
);
}
}
GettingStartedExample.propTypes={
markers: React.PropTypes.array.isRequired,
fetchMarkers: React.PropTypes.func.isRequired
}
function mapStateToProps(state){
return{
markers:state.markers
}
}
export default connect(mapStateToProps,{fetchMarkers})(GettingStartedExample);
Probably I have to set state of center to the last object in this.props.markers, I tried to do it on componentWillReceiveProps(), but I have no idea how to that.I also tried here in render():
if(markers[markers.length-1]!== undefined)
{
centerPos=markers[markers.length-1].props.position;
lastMark=markers[markers.length-1].props;
console.log(centerPos);
}
else {
centerPos={lat: 5.07074, lng: 19.915718};
}
and tried to pass it to the state, but it didn't work. I am sure the solution is simple, but I have no experience with React.If it would be helpful I am adding code of actions.js where redux action for fetching markers is defined:
export const SET_MARKERS='SET_MARKERS';
/*markers*/
export function setMarkers(markers){
return{
type:SET_MARKERS,
markers
}
}
export function fetchMarkers(){
return dispatch => {
fetch('/api/markers')
.then(res=>res.json())
.then(data=>dispatch(setMarkers(data.markers)));
;
}
}
Just add center property to GoogleMap component.
<GoogleMap
center={props.center}
/>

React+Redux - show InfoWindow on Marker click

I would like to display InfoWindow on Marker click. I followed some tutorials and I used react-google-maps for my project. I would like my app to work like this: "https://tomchentw.github.io/react-google-maps/basics/pop-up-window" but my code is a little bit different.
class Map extends React.Component {
handleMarkerClick(){
console.log("Clicked");
}
handleMarkerClose(){
console.log("CLOSE");
}
render(){
const mapContainer= <div style={{height:'100%',width:'100%'}}></div>
//fetch markers
const markers = this.props.markers.map((marker,i) => {
return (
<Marker key={i} position={marker.location} showTime={false} time={marker.time} onClick={this.handleMarkerClick} >
{
<InfoWindow onCloseClick={this.handleMarkerClose}>
<div>{marker.time}</div>
</InfoWindow>
}
</Marker>
)
})
/* set center equals to last marker's position */
var centerPos;
if(markers[markers.length-1]!== undefined)
{
centerPos=markers[markers.length-1].props.position;
}
else {
centerPos={};
}
return (
<GoogleMapLoader
containerElement={mapContainer}
googleMapElement={
<GoogleMap
defaultZoom={17}
center={centerPos}
>
{markers}
</GoogleMap>
}/>
);
}
}
export default Map;
I got "this.props.markers" from another class component, which fetching data from URL. I am almost sure, that it is easy problem to solve. Currently on marker click in console I got "Clicked" and on Marker close "CLOSE" as you can guess from above code it is because of handleMarkerClick() and handleMarkerClose(). I want to have pop-window with InfoWindow.
What should I do to make it work?
Here is heroku link : App on heroku
Hi I came across the same requirement. I did this (I am using redux and redux-thunk) :
GoogleMap.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {
withGoogleMap,
GoogleMap,
Marker,
InfoWindow
} from 'react-google-maps';
import { onMarkerClose } from '../actions/Cabs';
const GettingStartedGoogleMap = withGoogleMap(props => (
<GoogleMap
defaultZoom={12}
defaultCenter={{ lat: 12.9716, lng: 77.5946 }}
>
{props.markers.map( (marker, index) => (
<Marker {...marker} onClick={() => props.onMarkerClose(marker.key)}>
{marker.showInfo &&(
<InfoWindow onCloseClick={() => props.onMarkerClose(marker.key)}>
<div>
<h1>Popover Window</h1>
</div>
</InfoWindow>
)}
</Marker>
))}
</GoogleMap>
));
class CabType extends Component{
constructor(props){
super(props);
}
render(){
if(this.props.cabs.length === 0){
return <div>loading...</div>
}
return(
<div className="map-wrapper">
<GettingStartedGoogleMap
containerElement={
<div style={{ height: '100%' }} />
}
mapElement={
<div style={{ height: '100%' }} />
}
onMarkerClose = {this.props.onMarkerClose}
markers={this.props.showMap ? this.props.markers : []}
/>
</div>
)
}
}
export default connect(store => {return {
cabs : store.cabs,
markers: store.markers
}}, {
onMarkerClose
})(CabType);
Action.js
const getMarkers = (cabs , name) => dispatch => {
let markers = [];
let data = {};
cabs.map(cab => {
if(cab.showMap){
data = {
position: {
lat : cab.currentPosition.latitude,
lng : cab.currentPosition.longitude
},
showInfo: false,
key: cab.cabName,
icon: "/images/car-top.png",
driver: cab.driver,
contact: cab.driverContact,
};
markers.push(data);
}
});
dispatch(emitMarker(markers));
};
function emitSetMarker(payload){
return{
type: SET_MARKER,
payload
}
}
export const onMarkerClose = (key) => dispatch => {
dispatch(emitSetMarker(key))
};
RootReducer.js
import { combineReducers } from 'redux';
import { cabs } from "./Cabs";
import { markers } from "./Markers";
const rootReducer = combineReducers({
cabs,
markers,
});
export default rootReducer;
MarkerReducer.js
import { GET_MARKERS, SET_MARKER } from "../types"
export const markers = (state = [], action) => {
switch (action.type){
case GET_MARKERS:
return action.payload;
case SET_MARKER:
let newMarker = state.map(m => {
if(m.key === action.payload){
m.showInfo = !m.showInfo;
}
return m;
});
return newMarker;
default: return state;
}
};
Sorry for a long post but this is code which is tested and running. Cheers!