{"action":"created","issue":{"url":"https://api.github.com/repos/tomchentw/react-google-maps/issues/836","repository_url":"https://api.github.com/repos/tomchentw/react-google-maps","labels_url":"https://api.github.com/repos/tomchentw/react-google-maps/issues/836/labels{/name}","comments_url":"https://api.github.com/repos/tomchentw/react-google-maps/issues/836/comments","events_url":"https://api.github.com/repos/tomchentw/react-google-maps/issues/836/events","html_url":"https://github.com/tomchentw/react-google-maps/issues/836","id":325682202,"node_id":"MDU6SXNzdWUzMjU2ODIyMDI=","number":836,"title":"Fundamental performance problems with MarkerClusterer","user":{"login":"mschipperheyn","id":384959,"node_id":"MDQ6VXNlcjM4NDk1OQ==","avatar_url":"https://avatars3.githubusercontent.com/u/384959?v=4","gravatar_id":"","url":"https://api.github.com/users/mschipperheyn","html_url":"https://github.com/mschipperheyn","followers_url":"https://api.github.com/users/mschipperheyn/followers","following_url":"https://api.github.com/users/mschipperheyn/following{/other_user}","gists_url":"https://api.github.com/users/mschipperheyn/gists{/gist_id}","starred_url":"https://api.github.com/users/mschipperheyn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mschipperheyn/subscriptions","organizations_url":"https://api.github.com/users/mschipperheyn/orgs","repos_url":"https://api.github.com/users/mschipperheyn/repos","events_url":"https://api.github.com/users/mschipperheyn/events{/privacy}","received_events_url":"https://api.github.com/users/mschipperheyn/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-05-23T12:26:49Z","updated_at":"2018-07-29T00:53:49Z","closed_at":null,"author_association":"NONE","body":"I have tried and failed to resolve performance problems with having many markers using the MarkerClusterer. I now believe that the performance issue is an architectural limitation caused by the fact that for each Marker a `<div></div>` is rendered and performance decreases lineairly with increasing numbers of markers.\r\n\r\nThe MarkerClusterer is intended to deal with many markers and it's not working as advertised. I would recommend rewriting this and use the clusterer api more directly, avoiding a dom node for every marker. I can share the code I wrote based `google-map-react` as I was forced to move away from `react-google-maps`. Certainly not as elegant as it could be, but I was under a time crunch. "},"comment":{"url":"https://api.github.com/repos/tomchentw/react-google-maps/issues/comments/408644407","html_url":"https://github.com/tomchentw/react-google-maps/issues/836#issuecomment-408644407","issue_url":"https://api.github.com/repos/tomchentw/react-google-maps/issues/836","id":408644407,"node_id":"MDEyOklzc3VlQ29tbWVudDQwODY0NDQwNw==","user":{"login":"mschipperheyn","id":384959,"node_id":"MDQ6VXNlcjM4NDk1OQ==","avatar_url":"https://avatars3.githubusercontent.com/u/384959?v=4","gravatar_id":"","url":"https://api.github.com/users/mschipperheyn","html_url":"https://github.com/mschipperheyn","followers_url":"https://api.github.com/users/mschipperheyn/followers","following_url":"https://api.github.com/users/mschipperheyn/following{/other_user}","gists_url":"https://api.github.com/users/mschipperheyn/gists{/gist_id}","starred_url":"https://api.github.com/users/mschipperheyn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mschipperheyn/subscriptions","organizations_url":"https://api.github.com/users/mschipperheyn/orgs","repos_url":"https://api.github.com/users/mschipperheyn/repos","events_url":"https://api.github.com/users/mschipperheyn/events{/privacy}","received_events_url":"https://api.github.com/users/mschipperheyn/received_events","type":"User","site_admin":false},"created_at":"2018-07-29T00:53:49Z","updated_at":"2018-07-29T00:53:49Z","author_association":"NONE","body":"```\r\n/* global google */\r\nimport React from 'react';\r\nimport PropTypes from 'prop-types';\r\nimport GoogleMapReact from 'google-map-react';\r\nimport MarkerClustererPlus from 'marker-clusterer-plus';\r\nimport styles from './map.css';\r\n\r\nconst clusterIconStyles = [\r\n  {\r\n    height: 90,\r\n    textColor: '#ffffff',\r\n    url: '/img/senseo-90.png',\r\n    width: 90\r\n  }\r\n];\r\n\r\nconst markerClustererFactory = (map, markers) => {\r\n  const mcOptions = {\r\n    maxZoom: 15,\r\n    gridSize: 60,\r\n    enableRetinaIcons: true,\r\n    averageCenter: true,\r\n    styles: clusterIconStyles\r\n  };\r\n  return new MarkerClustererPlus(map, markers, mcOptions);\r\n};\r\n\r\nexport default class Map extends React.PureComponent {\r\n  static contextTypes = {\r\n    goApiId: PropTypes.string.isRequired\r\n  };\r\n\r\n  static propTypes = {\r\n    center: PropTypes.shape({\r\n      lat: PropTypes.number.isRequired,\r\n      lng: PropTypes.number.isRequired\r\n    }),\r\n    markers: PropTypes.arrayOf(\r\n      PropTypes.shape({\r\n        id: PropTypes.number.isRequired,\r\n        lng: PropTypes.number.isRequired,\r\n        lat: PropTypes.number.isRequired,\r\n        rating: PropTypes.number.isRequired\r\n      })\r\n    ),\r\n    zoom: PropTypes.number,\r\n    highlight: PropTypes.number,\r\n    onMarkerClick: PropTypes.func.isRequired\r\n  };\r\n\r\n  static defaultProps = {\r\n    center: {\r\n      lat: 52.092876,\r\n      lng: 5.10448\r\n    },\r\n    markers: [],\r\n    zoom: 8,\r\n    highlight: -1\r\n  };\r\n\r\n  state = {\r\n    draggable: true\r\n  };\r\n\r\n  componentWillMount() {\r\n    const { goApiId } = this.context;\r\n    this.mapConfig = {\r\n      key: goApiId,\r\n      v: '3.exp',\r\n      libraries: ['geometry', 'drawing', 'places']\r\n    };\r\n  }\r\n\r\n  componentDidMount() {\r\n    if (typeof window !== 'undefined') {\r\n      window.addEventListener('resize', this.updateWindowDimensions);\r\n      this.updateWindowDimensions();\r\n    }\r\n  }\r\n\r\n  componentDidUpdate(prevProps) {\r\n    const { markers } = this.props;\r\n    if (this.markerClusterer) {\r\n      if (prevProps.markers !== markers) this.drawMarkers();\r\n    } else if (typeof window !== 'undefined') {\r\n      this.loadInterval = setInterval(() => {\r\n        if (this.markerClusterer && markers.length > 0) {\r\n          clearInterval(this.loadInterval);\r\n          this.drawMarkers();\r\n        }\r\n      }, 1000);\r\n    }\r\n  }\r\n\r\n  componentWillUnmount() {\r\n    this.markerClusterer = null;\r\n    this.map = null;\r\n    if (typeof window !== 'undefined')\r\n      window.removeEventListener('resize', this.updateWindowDimensions);\r\n  }\r\n\r\n  handleRenderMarkers = map => {\r\n    const { markers } = this.props;\r\n    this.map = map.map;\r\n    if (!this.markerClusterer)\r\n      this.markerClusterer = markerClustererFactory(map.map, markers);\r\n    if (markers.length !== this.markerClusterer.getMarkers().length)\r\n      this.drawMarkers();\r\n  };\r\n\r\n  updateWindowDimensions = () => {\r\n    if (typeof window !== 'undefined')\r\n      this.setState({\r\n        draggable: window.innerWidth > 479.8\r\n      });\r\n  };\r\n\r\n  drawMarkers = () => {\r\n    const { markers, highlight, onMarkerClick } = this.props;\r\n    if (!this.markerClusterer) return;\r\n    google.maps.Marker.prototype.isDraggable = () => false;\r\n    const googleMarkers = markers.map(({ id, lng, lat }) => {\r\n      const marker = new google.maps.Marker({\r\n        map: this.map,\r\n        position: new google.maps.LatLng(lat, lng),\r\n        draggable: false,\r\n        icon:\r\n          id === highlight\r\n            ? '/img/senseo-pin-featured.png'\r\n            : '/img/senseo-pin.png'\r\n      });\r\n      google.maps.event.addListener(marker, 'click', () => {\r\n        onMarkerClick(id);\r\n      });\r\n      return marker;\r\n    });\r\n    this.markerClusterer.clearMarkers();\r\n    this.markerClusterer.addMarkers(googleMarkers, true);\r\n    this.markerClusterer.repaint();\r\n  };\r\n\r\n  render() {\r\n    const { zoom, center } = this.props;\r\n    return (\r\n      <div className={styles.mapContainer}>\r\n        <GoogleMapReact\r\n          bootstrapURLKeys={this.mapConfig}\r\n          defaultCenter={center}\r\n          defaultZoom={zoom}\r\n          onGoogleApiLoaded={this.handleRenderMarkers}\r\n          yesIWantToUseGoogleMapApiInternals\r\n        />\r\n      </div>\r\n    );\r\n  }\r\n}\r\n\r\n```"}}
{"actor":{"display_login":"mschipperheyn"}}