0
votes

Using react-google-maps with MarkerClusterer, how can I add and remove markers from the map/clusterer after the map is mounted, eg. when a button is clicked or in onMarkerClustererClick?

I've tried simply making a new Marker with map set to refs.map

      onMarkerClustererClick: () => (markerClusterer) => {
        const marker = new Marker({
          position: {lat: 56.565123, lng: 9.030908},
          map: refs.map,
          title: 'Hello World!'
        });
      },

as well as using the .addMarker() function defined in markerclustererplus used for MarkerClusterer in react-google-maps, but nothing works.

  onMarkerClustererClick: () => (markerClusterer) => {
    const marker = new Marker({
      position: {lat: 56.565123, lng: 9.030908},
      title: 'Hello World!'
    });

    refs.markerClusterer.addMarker(marker);
  },

which both returns the error Uncaught TypeError: Cannot read property '__SECRET_MARKER_CLUSTERER_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined.


Code based on the example from: https://tomchentw.github.io/react-google-maps/#markerclusterer

const MapWithAMarkerClusterer = compose(
  withProps({
    googleMapURL: "https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=AIzaSyATVkXuYRZCkB73ZsPEJisDy74GnVusIJw",
    loadingElement: <div style={{ height: `100%` }} />,
    containerElement: <div className="mapContainer" />,
    mapElement: <div style={{ height: `100%` }} />,
  }),
  withHandlers(() => {
    const refs = {
      map: undefined,
      markerClusterer: undefined,
    }

    return {
      onMapMounted: () => ref => {
        refs.map = ref
      },
      onMarkerClustererMounted: () => ref => {
        refs.markerClusterer = ref
      },
      onMarkerClustererClick: () => (markerClusterer) => {
        const marker = new Marker({
          position: {lat: 56.565123, lng: 9.030908},
          title: 'Hello World!'
        });

        refs.markerClusterer.addMarker(marker);
      },
    }
  }),
  withScriptjs,
  withGoogleMap
)(props =>
  <GoogleMap
    ref={props.onMapMounted}
    defaultZoom={3}
    defaultCenter={{ lat: 25.0391667, lng: 121.525 }}
  >
    <MarkerClusterer
      ref={props.onMarkerClustererMounted}
      onClick={props.onMarkerClustererClick}
      averageCenter
      enableRetinaIcons
      gridSize={60}
    >
      {props.hotels.results.map((item, index) => (
        <Marker
          key={index}
          position={{lat: parseFloat(item.latitude), lng: parseFloat(item.longitude) }}
        />
      ))}
    </MarkerClusterer>
  </GoogleMap>
);
1

1 Answers

1
votes

You must add markers with state-lat and state-lon near the cluster, if you try to change the props (which are immutable), the map will not be updated.

Here's an example how to add markers dinamically: SANDBOX EXAMPLE

Example below:

import React from "react";
import {
  withGoogleMap,
  GoogleMap,
  Marker,
  withScriptjs
} from "react-google-maps";

const Markers = ({ places }) => {
  return places.map(place => {
    return (
      <Marker key={place.id} position={{ lat: place.lat, lng: place.lng }} />
    );
  });
};

const Map = ({ places, zoom, center }) => {
  return (
    <GoogleMap defaultZoom={zoom} defaultCenter={center}>
      <Markers places={places} />
    </GoogleMap>
  );
};

const getRandomInRange = (from, to, fixed) => {
  return (Math.random() * (to - from) + from).toFixed(fixed) * 1;
};

class MapWithMarker extends React.Component {
  constructor(props) {
    super(props);
    this.state = { places: this.props.places }; //initialize initial state from props
  }

  addPlace() {
    const newPlace = {
      id: this.state.places.length + 1,
      lat: getRandomInRange(-30.0, -35.0, 3),
      lng: getRandomInRange(110.0, 150.0, 3)
    };
    this.setState(prevState => ({
      places: [...prevState.places, newPlace]
    }));

    /*if(this.state.places.length > 10) { 
      clearInterval(this.intervalId)
    }*/
  }

  componentDidMount() {
    this.intervalId = setInterval(this.addPlace.bind(this), 1000);
  }
  componentWillUnmount() {
    clearInterval(this.intervalId);
  }

  render() {
    return (
      <Map
        center={this.props.center}
        zoom={this.props.zoom}
        places={this.state.places}
      />
    );
  }
}

export default withScriptjs(withGoogleMap(MapWithMarker));

Tell me if this help you :)