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

Markers don't update location correctly according to state #959

Open khaledosman opened 5 years ago

khaledosman commented 5 years ago

The marker location doesn't update with state correctly the first time its changed, instead a third marker is created even though there're only two in state, if I do another setTimeout to update it, it updates the newly created one correctly. It seems like the library is caching & not removing the old markers on initial render or something similar.

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

class Map extends React.PureComponent {
  constructor (props) {
    super(props)
    this.state = {
      demoData: {
        'device:58fe8b4b-befd-4d03-837c-925fa5b61476': {
          'latitude': 52.51133948867925,
          'longitude': 13.406048111320755
        },
        'fake': {
          'latitude': 52.51115736666667,
          'longitude': 13.465472335185186
        }
      }
    }
    this.mapOptions = {
      zoomControl: true,
      mapTypeControl: false,
      scaleControl: true,
      streetViewControl: false,
      rotateControl: false,
      fullscreenControl: false
    }
  }

  componentDidMount () {
    setTimeout(() => {
      this.setState({ demoData: { ...this.state.demoData,
        ...{
          'fake': {
            'latitude': 52.51115736666667,
            'longitude': 13.485472335185186
          }
        } } })
    }, 5000)
  }

  renderMarkers () {
    const vendorLocations = this.state.demoData

    if (!vendorLocations) {
      return null
    }
    return Object.keys(vendorLocations)
      .map((vendorId) => {
        const { latitude, longitude } = vendorLocations[vendorId]
        return <Marker
          onMouseUp={this.handleMouseUp(latitude, longitude)}
          key={vendorId}
          icon='/images/ic_locationpin.svg'
          width='10'
          height={10}
          clickable
          position={{ lat: latitude, lng: longitude }} />
      })
  }
}

  render () {
    const { userCoords } = this.props

    return (
      <GoogleMap
        options={this.mapOptions}
        defaultZoom={12}
        defaultCenter={{ lat: userCoords.latitude, lng: userCoords.longitude }}
      >
        {this.renderMarkers()}
      </GoogleMap>
    )
  }
}

export default withScriptjs(withGoogleMap(Map))

Steps to reproduce

  1. Render initial Map
  2. Make a state change where a new marker should show up in the map
  3. Updating the location of either markers will create a new one instead of updating their locations and any subsequent changes to locations of either markers will update the newly created markers.
khaledosman commented 5 years ago

The issue seems to be due to React.StrictMode #921 , I still don't understand why react's strictMode would break this

JustFly1984 commented 5 years ago

@khaledosman try new updated version of this lib: @react-google-maps/api. We had been sured that it has no issues in StrictMode https://github.com/JustFly1984/react-google-maps-api/tree/master/packages/react-google-maps-api

khaledosman commented 5 years ago

I'm using the <DirectionsRenderer> component which doesn't seem to be supported in the updated version or in the docs here https://react-google-maps-api-docs.netlify.com/src-shapes .. Also the API is quite different I don't really want to rewrite the implementation.

JustFly1984 commented 5 years ago

@khaledosman My initial need was <DirectionsRenderer /> component for the project I'm working on: www.drivefromto.com There is an example for directions renderer in https://react-google-maps-api-gatsby-demo.netlify.com/

You can copy the code from here: https://github.com/JustFly1984/react-google-maps-api/blob/master/packages/react-google-maps-api-gatsby-example/src/examples/directions-renderer-example.js

JustFly1984 commented 5 years ago

@khaledosman also you can run gatsby.js example and play with it.