Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react-google-maps Marker Click Event

I am using the stock code for the clustered map posted on the react-google-maps documentation. I am trying to extend the code by adding a click event for the marker that will take the marker URL from the API and then call window.location to change the page.

Here is an example of one of the markers that is returned from my API:

{
  id: 1,
  name: "Oxford",
  slug: "oxford",
  lat: 51.752021,
  lng: -1.257726,
}

I have added an event onMarkerClick to the marker and the method is getting called properly. I hardcoded window.location and it gets called, I just don't know how to get the slug value.

I am assuming that I have to store the slug value differently from how I am doing it in the example below. I am new to React so I am probably missing something really obvious

import React from 'react'

const fetch = require("isomorphic-fetch");
const { compose, withProps, withHandlers } = require("recompose");
const {
  withScriptjs,
  withGoogleMap,
  GoogleMap,
  Marker
} = require("react-google-maps");
const { MarkerClusterer } = require("react-google-maps/lib/components/addons/MarkerClusterer");

const MapWithAMarkerClusterer = compose(
  withProps({
    googleMapURL: "https://maps.googleapis.com/maps/api/js?key=AIzaSyCvakAjEUpqfnucJu-CoClBD1CtTKZUGxQ&v=3.exp&libraries=geometry,drawing,places",
    loadingElement: <div style={{ height: 'calc(100vh - 56px)' }} />,
    containerElement: <div style={{ height: 'calc(100vh - 56px)' }} />,
    mapElement: <div style={{ height: 'calc(100vh - 56px)' }} />,
  }),
  withHandlers({
    onMarkerClustererClick: () => (markerClusterer) => {
      console.log('Clicked a cluster')
    },
    onMarkerClick: () => (marker) => {
      // link to post view page
      //
      //
      //
      //
      //
      console.log('Go to the marker post page')
      window.location = '/post/oxford';
    }
  }),
  withScriptjs,
  withGoogleMap
)(props =>
  <GoogleMap
    defaultZoom={3}
    defaultCenter={{ lat: 12.2637937, lng: 75.947508 }}
  >
    <MarkerClusterer
      onClick={props.onMarkerClustererClick}
      averageCenter
      enableRetinaIcons
      gridSize={60}
    >
      {props.markers.map(marker => (
        <Marker
          onClick={props.onMarkerClick}
          key={marker.id}
          position={{ lat: marker.lat, lng: marker.lng }}
          slug={marker.slug}
        />
      ))}
    </MarkerClusterer>
  </GoogleMap>
);

class TestMap extends React.PureComponent {
  componentWillMount() {
    this.setState({ markers: [] })
  }

  componentDidMount() {
    const url = '/api/posts';
    fetch(url)
      .then(res => res.json())
      .then(data => {
        this.setState({ markers: data });
      });
  }

  render() {
    return (
      <MapWithAMarkerClusterer markers={this.state.markers} />
    )
  }
}

export default TestMap
like image 281
Callum Avatar asked Nov 19 '17 14:11

Callum


1 Answers

In this example

<Marker
      onClick={props.onMarkerClick}
      key={marker.id}
      position={{ lat: marker.lat, lng: marker.lng }}
      slug={marker.slug}
/>

onMarkerClick: () => (marker) => {  //<- event object, not a marker object!  
   //.. 
}

a specific Google Maps event object is getting passed into onMarkerClick event handler instead of marker object.

You could utilize .bind to pass the marker object as a parameter like this:

<Marker
      key={marker.photo_id}
      position={{ lat: marker.latitude, lng: marker.longitude }}
      onClick={props.onMarkerClick.bind(this,marker)}
/>

And then given the structure of marker object:

{
  id: 1,
  name: "Oxford",
  slug: "oxford",
  lat: 51.752021,
  lng: -1.257726,
}

onMarkerClick event could be initialized like this:

onMarkerClick: () => (marker) => {
  window.location = '/post/' + marker.slug;
}
like image 175
Vadim Gremyachev Avatar answered Nov 15 '22 02:11

Vadim Gremyachev