Reputation: 772
I'm having issues with the react-google-maps module, namely with markers and component re-rendering.
This is the scenario:
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
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:
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
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