Reputation: 43
import React from 'react';
import {GoogleMap, withScriptjs, withGoogleMap, Marker} from 'react-google-maps';
import {db} from './Firebase';
import {useState, useEffect} from 'react';
import InfoWindow from 'react-google-maps/lib/components/InfoWindow';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import { CssBaseline } from '@material-ui/core';
import { makeStyles } from '@material-ui/styles';
import IconButton from '@material-ui/core/IconButton'
import KeyboardArrowLeftRounded from '@material-ui/icons/KeyboardArrowLeftOutlined';
const useStyles = makeStyles( theme =>({
appBar: {
backgroundColor: '#1976d2'
},
card :{
marginTop: 60
}
}));
const Maps = (props) =>
{
const classes = useStyles();
const [positions, setPosition] = useState([])
useEffect(() => {
const unsub = db.collection('Location').onSnapshot (snapshot => {
const allPositions = snapshot.docs.map(doc => ({
id: doc.id,
... doc.data()
}));
setPosition(allPositions);
})
return () => {
unsub();
};
}, [])
const WrappedMap = withScriptjs(withGoogleMap(props => (
<GoogleMap defaultZoom = {13}
defaultCenter = {{ lat: -1.292066 , lng : 36.821945}}>
{
positions.map(positioning => (
props.isMarkerShown &&
<Marker key = {positioning.id}
position = {{lat: positioning.Latitude , lng: positioning.Longitude}}
></Marker>
)
)
}
{
positions.map(positioning => (
<InfoWindow key = {positioning.id} defaultPosition = {{lat: positioning.Latitude, lng: positioning.Longitude}}>
<div>
{positioning.Team} <br/>
<a href = "/Nav"> Message </a>
</div>
</InfoWindow>
))
}
</GoogleMap>)));
return (
<div>
<div>
<CssBaseline/>
<AppBar position = "fixed" color = "primary" className = {classes.appBar}>
<Toolbar>
<IconButton color = "inherit" edge = "start" onClick={() => props.history.goBack()}>
<KeyboardArrowLeftRounded/>
</IconButton>
</Toolbar>
</AppBar>
</div>
<div>
<Card className = {classes.card}>
<CardContent>
<div style = {{width: "97vw", height: "90vh"}}>
<WrappedMap
isMarkerShown
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=AIzaSyD29SDFXKcqARovEjwUqKl0ysEFKK7GCmU`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
</CardContent>
</Card>
</div>
</div>
)
};
export default Maps;
I am using the code above to render markers and infowindows for locations that I'm fetching from Firebase. Currently when an update is made in Firebase, the whole mapview is rendered again in order to update the position of the markers and infowindows. How do I go about re-rendering just the marker when an update is made in Firebase.
Upvotes: 1
Views: 2866
Reputation: 59388
In your example WrappedMap
gets re-created every time. One solution (to prevent Google Maps API reload and maps re-render) would be to place the instantiation of WrappedMap
component outside of Maps
:
const WrappedMap = withScriptjs(
withGoogleMap(props => (
<GoogleMap
defaultZoom={5}
defaultCenter={{ lat: -24.9929159, lng: 115.2297986 }}
>
{props.places.map(
position =>
props.isMarkerShown && (
<Marker
key={position.id}
position={{
lat: position.lat,
lng: position.lng
}}
></Marker>
)
)}
</GoogleMap>
))
);
and then just pass positions
prop to reflect updated positions on map:
function Map() {
return (
<div>
<WrappedMap
isMarkerShown
positions={positions}
googleMapURL={`https://maps.googleapis.com/maps/api/js?key=AIzaSyD29SDFXKcqARovEjwUqKl0ysEFKK7GCmU`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `400px` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
}
Upvotes: 2
Reputation: 1920
You can prevent re-rendering by making use of PureComponent. In your case positioning is re-rendering the Marker and InfoWindow.
The Updated Code below will only re-render the updated/newly-added Markers.
import React from 'react';
import {GoogleMap, withScriptjs, withGoogleMap, Marker} from 'react-google-maps';
import {db} from './Firebase';
import {useState, useEffect} from 'react';
import InfoWindow from 'react-google-maps/lib/components/InfoWindow';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import { CssBaseline } from '@material-ui/core';
import { makeStyles } from '@material-ui/styles';
import IconButton from '@material-ui/core/IconButton'
import KeyboardArrowLeftRounded from '@material-ui/icons/KeyboardArrowLeftOutlined';
const useStyles = makeStyles( theme =>({
appBar: {
backgroundColor: '#1976d2'
},
card :{
marginTop: 60
}
}));
class MarkerPureComponent extends React.PureComponent {
render () {
return (
<Marker
position = {this.props.position}
>
</Marker>
)
}
}
class InfoWindowPureComponent extends React.PureComponent {
render () {
return (
<InfoWindow defaultPosition = {this.props.defaultPosition}>
{this.props.children}
</InfoWindow>
)
}
}
const Maps = (props) =>
{
const classes = useStyles();
const [positions, setPosition] = useState([])
useEffect(() => {
const unsub = db.collection('Location').onSnapshot (snapshot => {
const allPositions = snapshot.docs.map(doc => ({
id: doc.id,
... doc.data()
}));
setPosition(allPositions);
})
return () => {
unsub();
};
}, [])
const WrappedMap = withScriptjs(withGoogleMap(props => (
<GoogleMap defaultZoom = {13}
defaultCenter = {{ lat: -1.292066 , lng : 36.821945}}>
{
positions.map(positioning => (
props.isMarkerShown &&
<MarkerPureComponent key = {positioning.id}
position = {{lat: positioning.Latitude , lng: positioning.Longitude}}
></MarkerPureComponent>
)
)
}
{
positions.map(positioning => (
<InfoWindowPureComponent key = {positioning.id} defaultPosition = {{lat: positioning.Latitude, lng: positioning.Longitude}}>
<div>
{positioning.Team} <br/>
<a href = "/Nav"> Message </a>
</div>
</InfoWindowPureComponent>
))
}
</GoogleMap>)));
return (
<div>
<div>
<CssBaseline/>
<AppBar position = "fixed" color = "primary" className = {classes.appBar}>
<Toolbar>
<IconButton color = "inherit" edge = "start" onClick={() => props.history.goBack()}>
<KeyboardArrowLeftRounded/>
</IconButton>
</Toolbar>
</AppBar>
</div>
<div>
<Card className = {classes.card}>
<CardContent>
<div style = {{width: "97vw", height: "90vh"}}>
<WrappedMap
isMarkerShown
googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=AIzaSyD29SDFXKcqARovEjwUqKl0ysEFKK7GCmU`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
</CardContent>
</Card>
</div>
</div>
)
};
export default Maps;
Upvotes: 0