google-maps-react icon indicating copy to clipboard operation
google-maps-react copied to clipboard

Clicking on infowindow and then back to map rerenders markers.

Open themakerman opened this issue 6 years ago • 15 comments

Why are markers rerendered everytime there is some interaction with infowindow?

themakerman avatar Oct 15 '18 03:10 themakerman

this project does not use react very well. the authors wrote this so they could market their book. ironically marketed by saying "learn react the right way"

https://reactjs.org/docs/react-component.html#shouldcomponentupdate

Use shouldComponentUpdate() to let React know if a component’s output is not affected by the current change in state or props. The default behavior is to re-render on every state change, and in the vast majority of cases you should rely on the default behavior.

Qwiso avatar Oct 15 '18 13:10 Qwiso

@Qwiso do you know any other library which doesn't requires too much setup... I did tried using should ComponentUpdate but too much of if statements and still for one case I am unable to handle the update.... This updating thing should be part of core module only then it will work in all scenarios. Would be great if you can tell me any other library.

themakerman avatar Oct 15 '18 15:10 themakerman

even if I update other state variables on the screen/component which are not used for map component also rerendering the map component. This should not be expected behaviour does anyone know how to fix it ?

kashifaliquazi avatar Oct 16 '18 08:10 kashifaliquazi

@kashifaliquazi yup it is happening. Mayb to keep mapview away from redux? Thats the only way i think to avoid rerendering

themakerman avatar Oct 24 '18 06:10 themakerman

To solve this issue of re-rendering and to allow for editing of SVG data which is mentioned in other issues, I implemented a new property in Marker.js and changed the logic of the componentDidUpdate method

{
	  key: 'componentDidUpdate',
	  value: function componentDidUpdate(prevProps) {
			if (this.props.shouldRender) {
			  this.marker.setMap(null)
			  this.renderMarker()
			}
	  }
}

in the render method of my map view, I create each marker based on custom object I am using from the state

let userMarkers = this.state.userMarkers.map((marker, index) => {
	let userMarker = <Marker
		key={index}
		name={marker.name}
		position={marker.position}
		icon={marker.iconSVG}
		onClick={this.onMarkerClick}
		shouldRender={marker.shouldRender}
	/>
	marker.shouldRender = false
	return userMarker 
})

and finally,

  <Map
	styles={this.state.mapStyle}
	onClick={this.onMapClicked}
	google={this.props.google}
	zoom={10}
	center={this.state.panToPos ? this.state.panToPos : null}
  >
	{userMarkers}
</Map>

Qwiso avatar Oct 24 '18 12:10 Qwiso

@Qwiso

{
	  key: 'componentDidUpdate',
	  value: function componentDidUpdate(prevProps) {
			if (this.props.shouldRender) {
			  this.marker.setMap(null)
			  this.renderMarker()
			}
	  }
}

Is this ES5?

themakerman avatar Oct 25 '18 05:10 themakerman

@themakerman it's just the part of the source code that i've changed. Marker.js from google-maps-react module. that what it looks like. not sure if it's ES5

Qwiso avatar Oct 25 '18 15:10 Qwiso

@Qwiso Ohh i got it. You edited the module itself. Why not PR?

themakerman avatar Oct 26 '18 03:10 themakerman

@themakerman because, as written, it's a breaking change to the existing functionality. it's not a great way of doing things but it works for me

Qwiso avatar Oct 26 '18 17:10 Qwiso

Extending the Marker component works in the meantime until the comparison fix is merged:

class CustomMarker extends Marker {
  componentDidUpdate(prevProps) {
    if(
      this.props.map !== prevProps.map || 
      this.props.icon.url !== prevProps.icon.url || 
      (
        this.props.position.lat !== prevProps.position.lat || 
        this.props.position.lng !== prevProps.position.lng
      )
    ) {
      if(this.marker) {
        this.marker.setMap(null);
      }
      this.renderMarker();
    }
  }
}

srobertson421 avatar Jun 15 '19 05:06 srobertson421

@srobertson421 , Your solution is pretty nice, but still forces me to pass property icon otherwise I will get error, so I do a little patch hope it helps:

class CustomMarker extends Marker {
  componentDidUpdate(prevProps) {
    if(
      this.props.map !== prevProps.map || 
      (this.props.icon && ( this.props.icon.url !== prevProps.icon.url )) || 
      (
        this.props.position.lat !== prevProps.position.lat || 
        this.props.position.lng !== prevProps.position.lng
      )
    ) {
      if(this.marker) {
        this.marker.setMap(null);
      }
      this.renderMarker();
    }
  }
}

radinreth avatar Aug 01 '19 03:08 radinreth

When I use custom url for marker, it re renders the marker. Is there any solution to fix that ?

sridaradappt avatar May 08 '20 21:05 sridaradappt

@radinreth and @srobertson421 - sending many many blessings to your and your family and your cousin and friends. I couldn't knock it and your code works beautifully.

teadams avatar Aug 31 '20 03:08 teadams

Extending the Marker component works in the meantime until the comparison fix is merged:

class CustomMarker extends Marker {
  componentDidUpdate(prevProps) {
    if(
      this.props.map !== prevProps.map || 
      this.props.icon.url !== prevProps.icon.url || 
      (
        this.props.position.lat !== prevProps.position.lat || 
        this.props.position.lng !== prevProps.position.lng
      )
    ) {
      if(this.marker) {
        this.marker.setMap(null);
      }
      this.renderMarker();
    }
  }
}

What is the status of this? Is it already integrated into the lib?

kevinvugts avatar Jan 12 '21 07:01 kevinvugts

@kevinvugts currently this is still the only workaround. This library isn't very well supported.

dannyVortexIoT avatar Feb 04 '21 16:02 dannyVortexIoT