Google Map React Component Tutorial
A declarative Google Map React component using React, lazy-loading dependencies, current-location finder and a test-driven approach by the Fullstack React team.
Quickstart
First, install the library:
npm install --save google-maps-react
Automatically Lazy-loading Google API
The library includes a helper to wrap around the Google maps API. The GoogleApiWrapper
Higher-Order component accepts a configuration object which must include an apiKey
. See lib/GoogleApi.js for all options it accepts.
import {GoogleApiWrapper} from 'google-maps-react';
// ...
export class MapContainer extends React.Component {}
export default GoogleApiWrapper({
apiKey: (YOUR_GOOGLE_API_KEY_GOES_HERE)
})(MapContainer)
If you want to add a loading container other than the default loading container, simply pass it in the HOC, like so:
const LoadingContainer = (props) => (
<div>Fancy loading container!</div>
)
export default GoogleApiWrapper({
apiKey: (YOUR_GOOGLE_API_KEY_GOES_HERE),
LoadingContainer: LoadingContainer
})(MapContainer)
Sample Usage With Lazy-loading Google API:
import {Map, InfoWindow, Marker, GoogleApiWrapper} from 'google-maps-react';
export class MapContainer extends Component {
render() {
return (
<Map google={this.props.google} zoom={14}>
<Marker onClick={this.onMarkerClick}
name={'Current location'} />
<InfoWindow onClose={this.onInfoWindowClose}>
<div>
<h1>{this.state.selectedPlace.name}</h1>
</div>
</InfoWindow>
</Map>
);
}
}
export default GoogleApiWrapper({
apiKey: (YOUR_GOOGLE_API_KEY_GOES_HERE)
})(MapContainer)
Note: Marker and InfoWindow components are disscussed below.
Additional Map Props
The Map component takes a number of optional props.
Zoom: (Shown Above) takes a number with the higher value representing a tighter focus on the map's center.
Style: Takes CSS style object - commonly width and height.
const style = {
width: '100%',
height: '100%'
}
initalCenter: Takes an object containing latitude and longitude coordinates. Sets the maps center upon loading.
<Map
google={this.props.google}
style={style}
initialCenter={{
lat: 40.854885,
lng: -88.081807
}}
zoom={15}
onClick={this.onMapClicked}
>
center: Takes an object containing latitude and longitude coordinates. Use this if you want to re-render the map after the initial render.
<Map
google={this.props.google}
style={style}
center={{
lat: 40.854885,
lng: -88.081807
}}
zoom={15}
onClick={this.onMapClicked}
>
It also takes event handlers described below:
Events
The <Map />
component handles events out of the box. All event handlers are optional.
onReady
When the <Map />
instance has been loaded and is ready on the page, it will call the onReady
prop, if given. The onReady
prop is useful for fetching places or using the autocomplete API for places.
React.createClass({
fetchPlaces: function(mapProps, map) {
const {google} = mapProps;
const service = new google.maps.places.PlacesService(map);
// ...
},
render: function() {
return (
<Map google={this.props.google}
onReady={this.fetchPlaces}
visible={false}>
<Listing places={this.state.places} />
</Map>
)
}
});
onClick
To listen for clicks on the <Map />
component, pass the onClick
prop:
React.createClass({
mapClicked: function(mapProps, map, clickEvent) {
// ...
},
render: function() {
return (
<Map google={this.props.google}
onClick={this.mapClicked} />
)
}
});
onDragend
When our user changes the map center by dragging the Map around, we can get a callback after the event is fired with the onDragend
prop:
React.createClass({
centerMoved: function(mapProps, map) {
// ...
},
render: function() {
return (
<Map google={this.props.google}
onDragend={this.centerMoved} />
)
}
});
Visibility
You can control the visibility of the map by using the visible
prop. This is useful for situations when you want to use the Google Maps API without a map. The <Map />
component will load like normal. See the Google places demo
For example:
<Map google={this.props.google}
visible={false}>
<Listing places={this.state.places} />
</Map>
Subcomponents
The <Map />
api includes subcomponents intended on being used as children of the Map
component. Any child can be used within the Map
component and will receive the three props
(as children):
map
- the Google instance of themap
google
- a reference to thewindow.google
objectmapCenter
- thegoogle.maps.LatLng()
object referring to the center of the map instance
Marker
To place a marker on the Map, include it as a child of the <Map />
component.
<Map google={this.props.google}
style={{width: '100%', height: '100%', position: 'relative'}}
className={'map'}
zoom={14}>
<Marker
title={'The marker`s title will appear as a tooltip.'}
name={'SOMA'}
position={{lat: 37.778519, lng: -122.405640}} />
<Marker
name={'Dolores park'}
position={{lat: 37.759703, lng: -122.428093}} />
<Marker />
<Marker
name={'Your position'}
position={{lat: 37.762391, lng: -122.439192}}
icon={{
url: "/path/to/custom_icon.png",
anchor: new google.maps.Point(32,32),
scaledSize: new google.maps.Size(64,64)
}} />
</Map>
The <Marker />
component accepts a position
prop that defines the location for the position
on the map. It can be either a raw object or a google.maps.LatLng()
instance.
If no position
is passed in the props
, the marker will default to the current position of the map, i.e. the mapCenter
prop.
You can also pass any other props
you want with the <Marker />
. It will be passed back through marker events.
Events
The <Marker />
component listens for events, similar to the <Map />
component.
onClick
You can listen for an onClick
event with the (appropriately named) onClick
prop.
const WithMarkers = React.createClass({
onMarkerClick: function(props, marker, e) {
},
render: function() [
return (
<Map google={this.props.google}>
<Marker onClick={this.onMarkerClick}
name={'Current location'} />
</Map>
)
]
});
mouseover
You can also pass a callback when the user mouses over a <Marker />
instance by passing the onMouseover
callback:
const Container = React.createClass({
onMouseoverMarker: function(props, marker, e) {
},
render: function() [
return (
<Map google={this.props.google}>
<Marker onMouseover={this.onMouseoverMarker}
name={'Current location'} />
</Map>
)
]
});
Polygon
To place a polygon on the Map, set <Polygon />
as child of Map component.
render: function() {
var triangleCoords = [
{lat: 25.774, lng: -80.190},
{lat: 18.466, lng: -66.118},
{lat: 32.321, lng: -64.757},
{lat: 25.774, lng: -80.190}
];
return(
<Map google={this.props.google}
style={{width: '100%', height: '100%', position: 'relative'}}
className={'map'}
zoom={14}>
<Polygon
paths={triangleCoords}
strokeColor="#0000FF"
strokeOpacity={0.8}
strokeWeight={2}
fillColor="#0000FF"
fillOpacity={0.35} />
</Map>
)
}
Events
The <Polygon />
component listens to onClick
, onMouseover
and onMouseout
events.
Polyline
To place a polyline on the Map, set <Polyline />
as child of Map component.
render: function() {
var triangleCoords = [
{lat: 25.774, lng: -80.190},
{lat: 18.466, lng: -66.118},
{lat: 32.321, lng: -64.757},
{lat: 25.774, lng: -80.190}
];
return(
<Map google={this.props.google}
style={{width: '100%', height: '100%', position: 'relative'}}
className={'map'}
zoom={14}>
<Polyline
paths={triangleCoords}
strokeColor="#0000FF"
strokeOpacity={0.8}
strokeWeight={2} />
</Map>
)
}
Events
The <Polyline />
component listens to onClick
, onMouseover
and onMouseout
events.
InfoWindow
The <InfoWindow />
component included in this library is gives us the ability to pop up a "more info" window on our Google map.
The visibility of the <InfoWindow />
component is controlled by a visible
prop. The visible
prop is a boolean (PropTypes.bool
) that shows the <InfoWindow />
when true and hides it when false.
There are two ways how to control a position of the <InfoWindow />
component.
You can use a position
prop or connect the <InfoWindow />
component directly to an existing <Marker />
component by using a marker
prop.
//note: code formatted for ES6 here
export class MapContainer extends Component {
constructor(props) {
super(props);
this.state = {
showingInfoWindow: false,
activeMarker: {},
selectedPlace: {},
}
// binding this to event-handler functions
this.onMarkerClick = this.onMarkerClick.bind(this);
this.onMapClicked = this.onMapClicked.bind(this);
}
onMarkerClick: function(props, marker, e) {
this.setState({
selectedPlace: props,
activeMarker: marker,
showingInfoWindow: true
});
},
onMapClicked: function(props) {
if (this.state.showingInfoWindow) {
this.setState({
showingInfoWindow: false,
activeMarker: null
})
}
},
render: function() {
return (
<Map google={this.props.google}
onClick={this.onMapClicked}>
<Marker onClick={this.onMarkerClick}
name={'Current location'} />
<InfoWindow
marker={this.state.activeMarker}
visible={this.state.showingInfoWindow}>
<div>
<h1>{this.state.selectedPlace.name}</h1>
</div>
</InfoWindow>
</Map>
)
}
});
Events
The <InfoWindow />
throws events when it's showing/hiding. Every event is optional and can accept a handler to be called when the event is fired.
<InfoWindow
onOpen={this.windowHasOpened}
onClose={this.windowHasClosed}
visible={this.state.showingInfoWindow}>
<div>
<h1>{this.state.selectedPlace.name}</h1>
</div>
</InfoWindow>
onClose
The onClose
event is fired when the <InfoWindow />
has been closed. It's useful for changing state in the parent component to keep track of the state of the <InfoWindow />
.
onOpen
The onOpen
event is fired when the window has been mounted in the Google map instance. It's useful for keeping track of the state of the <InfoWindow />
from within the parent component.
The GoogleApiWrapper
automatically passes the google
instance loaded when the component mounts (and will only load it once).
Manually loading the Google API
If you prefer not to use the automatic loading option, you can also pass the window.google
instance as a prop
to your <Map />
component.
<Map google={window.google} />
Issues?
If you have some issues, please make an issue on the issues tab and try to include an example. We've had success with https://codesandbox.io
An example template might look like: https://codesandbox.io/s/x3xxjr7r04
Contributing
git clone https://github.com/fullstackreact/google-maps-react.git
cd google-maps-react
npm install
make dev
The Google Map React component library uses React and the Google API to give easy access to the Google Maps library.