Callum
Callum

Reputation: 1165

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

Upvotes: 6

Views: 22204

Answers (2)

andyrandy
andyrandy

Reputation: 74014

You can create a custom component for the Marker and identify it by an additional parameter - for example, an id:

import React from 'react';
import {Marker} from 'react-google-maps';

const CustomMarker = (props) => {
    const {id} = props;

    const onMarkerClick = (evt) => {
        console.log(id);
    };

    return (
        <Marker
            onClick={onMarkerClick}
            {...props}
        />
    );
};

export default CustomMarker;

Upvotes: 6

Vadim Gremyachev
Vadim Gremyachev

Reputation: 59368

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;
}

Upvotes: 6

Related Questions