Edeph
Edeph

Reputation: 772

React google maps Markers disappear after component re-render

I'm having issues with the react-google-maps module, namely with markers and component re-rendering.

This is the scenario:

  1. Load page with map and 2-3 markers on it (ok)
  2. Click a tab on the nav-bar -> page renders something else in a single page app fashion (ok)
  3. Click the tab on the nav-bar that leads back to the map -> page renders the map but the markers are not rendered.

I am holding marker data in the state and i am applying them to the map in the onGoogleApiLoaded={({map, maps}) => this.renderMarkers(map, maps)}.

I managed to solve this problem by wrapping renderMarkers in a setTimeout of one second and it loads fine this way.

I don't like this solution and i believe that i simply don't do it the way i should. I believe the markers try to place themselves on the map that is not rendered but it's curious that even withoutsetTimeout it works for the default page (probably something to do with react component lifecycle, i don't know).

Is there a way to attach the property onGoogleApiLoaded={({map, maps}) => this.renderMarkers(map, maps)} after the map is completely loaded ? Or at least delay it until i'm 100% sure that the map is loaded and not some random number of seconds.

EDIT: I was assigning the markers with the marker.setMap(map) method and i just tried setting up the property map: map in the marker's constructor but the behaviour stays the same.

Upvotes: 2

Views: 4122

Answers (2)

Edeph
Edeph

Reputation: 772

I got this figured out after i've broken down the problem a bit more. The issue was caused by the fact that i was losing the marker data that was kept in the state of the Map component (which is a child to the component that has the nav-bar).

So the flow was like this:

  1. First render of the page -> everything loads fine because everything gets rendered for the first time (including markers).
  2. I render another component, the previous one is destroyed and loses state.
  3. I re-render the Map component but it has no state, so it has no data for the markers to use.

Naturally the solution was to move the state one level higher into the parent and pass it down as a prop of Map component and now everything works as it should.

BONUS:

I want to mention another thing that i had to fix but won't be necessarily useful for the others that stumble upon this issue: I was using a nav-bar to route through my pages (using react-router-dom).

When moving the state a level higher into the parent, the parameters won't be passed to the <Route element like so: <Route path="/" component={Map} markerData={this.state.markerData}/> but rather using the render property like this: <Route exact path="/" render={props => <Map markerData={this.state.markerData}/>} so that the Map component gets the props and not the Router.

Upvotes: 1

Rodius
Rodius

Reputation: 2311

When you say you click on a tab and the page renders something else you are probably unmounting your map component. If you have your markers saved in the state as you say you can check this for yourself in the componentWillUnmount.

componentWillUnmount() {
  console.log('Unmount');
}

If that console log is shown in your console that means you're unmounting your component and losing the markers data you have in your state.

Now, in order to load the map with your markers you can wait for the map to load completely with componentDidMount. I'm not sure how react-google-maps differs from react-leaflet (the map component I have experience with) but I'm guessing the map has a property where you pass it the markers you're keeping in the state. Instead of a timeout you should probably use componentWillMount or componentDidUnmount react life cycle method to get your markers data.

componentDidMount() { // It should work with componentWillMount too
  this.fetchMarkersData();
}

fetchMarkersData() {
  // ... get your data
  this.setState({ markers: markersData });
}

render() {
  return (
    <MapComponent
      markers={this.state.markers}
    />
  );
}

Upvotes: 0

Related Questions