0

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 Answer 1

1

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 :)

Sign up to request clarification or add additional context in comments.

1 Comment

ready, I gave an example, anyway I had provided a link to codebox

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.