tomchentw / react-google-maps

React.js Google Maps integration component
https://tomchentw.github.io/react-google-maps/
MIT License
4.62k stars 939 forks source link

MarkerClusterer raise error when adding new marker #1042

Open bobo8488 opened 4 years ago

bobo8488 commented 4 years ago

Hi all, is there a way to refresh MarkerClusterer when receive new props from my parent component? Now I'm doing this

const MapWithASearchBox = compose(
  withProps({
    googleMapURL: "https://maps.googleapis.com/maps/api/js?key=hidden&v=3.exp&language=it&libraries=geometry,drawing,places",
    loadingElement: <div style={{ height: `100%` }} />,
    containerElement: <div style={{ height: `400px` }} />,
    mapElement: <div style={{ height: `100%` }} />,
  }),
  lifecycle({
    componentDidMount(){
      console.log(this);
      // this.mapInstance = this.mapNode.context[MAP];
    },
    componentDidUpdate(prevProps,prevState){
      console.log(this);
      // console.log("Update");
      // console.log(this.props.selectedServicePoint);
      // console.log("componentDiUpdate called");
    },
    componentWillMount() {
      const refs = {}

      this.setState({
        bounds: null,
        // center: {
        //   // lat: this.props.servicePoints[0].latitude, lng: this.props.servicePoints[0].longitude
        //   lat: this.props.selectedServicePoint.latitude, lng: this.props.selectedServicePoint.longitude
        // },
        markers: [],
        // servicePoints:[],
        onMapMounted: ref => {
          refs.map = ref;
        },
        onBoundsChanged: () => {
          this.setState({
            bounds: refs.map.getBounds(),
            center: refs.map.getCenter(),
          })
        },
        onSearchBoxMounted: ref => {
          refs.searchBox = ref;
        },
        getMarkers:(data)=>{

        },
        onPlacesChanged: () => {
          const places = refs.searchBox.getPlaces();
          const bounds = new google.maps.LatLngBounds();

          places.forEach(place => {
            if (place.geometry.viewport) {
              bounds.union(place.geometry.viewport)
            } else {
              bounds.extend(place.geometry.location)
            }
          });
          const nextMarkers = places.map(place => ({
            position: place.geometry.location,
          }));
          const nextCenter = _.get(nextMarkers, '0.position', this.state.center);

          this.setState({
            center: nextCenter,
            markers: nextMarkers,
          });
          // refs.map.fitBounds(bounds);
        },
      })
    },
  }),
  withHandlers({
    onMarkerClustererClick: () => (markerClusterer) => {
      const clickedMarkers = markerClusterer.getMarkers()
      console.log(`Current clicked markers length: ${clickedMarkers.length}`)
      console.log(clickedMarkers)
    },
  }),
  withStateHandlers(() => ({
    isOpen: {},
  }), {
    onToggleOpen: ({ isOpen }) => (id) => ({
      isOpen: {
        ...isOpen,
        [id]:isOpen[id]==undefined?true:!isOpen[id]
      },
    })
  }),
  withScriptjs,
  withGoogleMap
)(props =>{
  return <GoogleMap
    ref={props.onMapMounted}
    defaultZoom={11}
    center={{
      lat: props.selectedServicePoint.latitude, lng: props.selectedServicePoint.longitude
    }}
    zoom={11}
    options={{
      gestureHandling:'cooperative',
      streetViewControl:false,
      fullscreenControl:false
    }}
  // onBoundsChanged={props.onBoundsChanged}
  >
    <MarkerClusterer
      onClick={props.onMarkerClustererClick}
      averageCenter
      enableRetinaIcons
      gridSize={60}
    >
      {props.servicePoints.map((x) =>
        <Marker
          onClick={()=>{
            props.onToggleOpen(x.id);
          }}
          animation={google.maps.Animation.DROP}
          key={x.id}
          icon={{
            url: 'assets/images/maps/Preferenza'+x.idTipoPreferenza+'.png', // url
            scaledSize: new google.maps.Size(50, 50), // scaled size
            origin: new google.maps.Point(0,0), // origin
            anchor: new google.maps.Point(0, 0) // anchor
          }}
          position={{ lat: x.latitude, lng: x.longitude }}
        >
          {props.isOpen[x.id]===true &&
            <InfoWindow
              key={x.id}
              options={{ closeBoxURL: ``, enableEventPropagation: true }}
              onCloseClick={()=>{
                props.onToggleOpen(x.id);
              }}>
              <div>
                <strong><label>{x.name}</label></strong><br></br>
                <em><label>{x.description}</label></em><br></br>
                <label>{x.address}</label>
              </div>
            </InfoWindow>}
         </Marker>
      )}
    </MarkerClusterer>

  </GoogleMap>
  }
);

But when I get updated values (props.servicePoints) from the server, an error appear to me image

I saw that the error seems to be related to MarkerClusterer, because if I comment the MarkerClusterer code, all is working fine. Any ideas? Thank you so much for your help!

JustFly1984 commented 4 years ago

The repo of this project is unmaintained more than a year, and we had build new version https://www.npmjs.com/package/@react-google-maps/api

We had rewrite it to TypeScript, and updating it frequently: https://github.com/JustFly1984/react-google-maps-api/tree/master/packages/react-google-maps-api You can enjoy autocomplete.

You can see our docs: https://react-google-maps-api-docs.netlify.app

Also a lot of examples: https://react-google-maps-api-gatsby-demo.netlify.app/ https://github.com/JustFly1984/react-google-maps-api/tree/master/packages/react-google-maps-api-gatsby-example/src/examples

The bundle size is much smaller: https://bundlephobia.com/result?p=@react-google-maps/api

Our Spectrum community: https://spectrum.chat/react-google-maps
Our Slack channel: https://join.slack.com/t/react-google-maps-api/shared_invite/enQtODc5ODU1NTY5MzQ4LTBiNTYzZmY1YmVjYzJhZThkMGU0YzUwZjJkNGJmYjk4YjQyYjZhMDk2YThlZGEzNDc0M2RhNjBmMWE4ZTJiMjQ

Enjoy!