- Notifications
You must be signed in to change notification settings - Fork817
Companion code to the "How to Write a Google Maps React Component" Tutorial
License
fullstackreact/google-maps-react
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A declarative Google Map React component using React, lazy-loading dependencies, current-location finder and a test-driven approach by theFullstack React team.
See thedemo andaccompanying blog post.
First, install the library:
npm install --save google-maps-react
The library includes a helper to wrap around the Google maps API. TheGoogleApiWrapper
Higher-Order component accepts a configuration object whichmust include anapiKey
. Seelib/GoogleApi.js for all options it accepts.
import{GoogleApiWrapper}from'google-maps-react';// ...exportclassMapContainerextendsReact.Component{}exportdefaultGoogleApiWrapper({apiKey:(YOUR_GOOGLE_API_KEY_GOES_HERE)})(MapContainer)
Alternatively, theGoogleApiWrapper
Higher-Order component can be configured by passing a function that will be called with whe wrapped component'sprops
and should returned the configuration object.
exportdefaultGoogleApiWrapper((props)=>({apiKey:props.apiKey,language:props.language,}))(MapContainer)
If you want to add a loading containerother than the default loading container, simply pass it in the HOC, like so:
constLoadingContainer=(props)=>(<div>Fancy loading container!</div>)exportdefaultGoogleApiWrapper({apiKey:(YOUR_GOOGLE_API_KEY_GOES_HERE),LoadingContainer:LoadingContainer})(MapContainer)
import{Map,InfoWindow,Marker,GoogleApiWrapper}from'google-maps-react';exportclassMapContainerextendsComponent{render(){return(<Mapgoogle={this.props.google}zoom={14}><MarkeronClick={this.onMarkerClick}name={'Current location'}/><InfoWindowonClose={this.onInfoWindowClose}><div><h1>{this.state.selectedPlace.name}</h1></div></InfoWindow></Map>);}}exportdefaultGoogleApiWrapper({apiKey:(YOUR_GOOGLE_API_KEY_GOES_HERE)})(MapContainer)
Note:Marker andInfoWindow components are disscussed below.
Check out the example site at:http://fullstackreact.github.io/google-maps-react
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.
conststyle={width:'100%',height:'100%'}
Container Style: Takes CSS style object - optional, commonly when you want to change from the default of position "absolute".
constcontainerStyle={position:'relative',width:'100%',height:'100%'}
<MapcontainerStyle={containerStyle}
initialCenter: Takes an object containing latitude and longitude coordinates. Sets the maps center upon loading.
<Mapgoogle={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.
<Mapgoogle={this.props.google}style={style}center={{lat:40.854885,lng:-88.081807}}zoom={15}onClick={this.onMapClicked}>
bounds: Takes agoogle.maps.LatLngBounds() object to adjust the center and zoom of the map.
varpoints=[{lat:42.02,lng:-77.01},{lat:42.03,lng:-77.02},{lat:41.03,lng:-77.04},{lat:42.05,lng:-77.02}]varbounds=newthis.props.google.maps.LatLngBounds();for(vari=0;i<points.length;i++){bounds.extend(points[i]);}return(<Mapgoogle={this.props.google}initialCenter={{lat:42.39,lng:-72.52}}bounds={bounds}></Map>);
The following props are boolean values for map behavior:scrollwheel
,draggable
,keyboardShortcuts
,disableDoubleClickZoom
The following props are boolean values for presence of controls on the map:zoomControl
,mapTypeControl
,scaleControl
,streetViewControl
,panControl
,rotateControl
,fullscreenControl
The following props are object values for control options such as placement of controls on the map:zoomControlOptions
,mapTypeControlOptions
,streetViewControlOptions
See Google MapsControls for more information.
It also takes event handlers described below:
The<Map />
component handles events out of the box. All event handlers are optional.
When the<Map />
instance has been loaded and is ready on the page, it will call theonReady
prop, if given. TheonReady
prop is useful for fetching places or using the autocomplete API for places.
fetchPlaces(mapProps,map){const{google}=mapProps;constservice=newgoogle.maps.places.PlacesService(map);// ...}render(){return(<Mapgoogle={this.props.google}onReady={this.fetchPlaces}visible={false}><Listingplaces={this.state.places}/></Map>)}
To listen for clicks on the<Map />
component, pass theonClick
prop:
mapClicked(mapProps,map,clickEvent){// ...}render(){return(<Mapgoogle={this.props.google}onClick={this.mapClicked}/>)}
When our user changes the map center by dragging the Map around, we can get a callback after the event is fired with theonDragend
prop:
centerMoved(mapProps,map){// ...}render(){return(<Mapgoogle={this.props.google}onDragend={this.centerMoved}/>)}
The<Map />
component also listens toonRecenter
,onBounds_changed
,onCenter_changed
,onDblclick
,onDragstart
,onHeading_change
,onIdle
,onMaptypeid_changed
,onMousemove
,onMouseout
,onMouseover
,onProjection_changed
,onResize
,onRightclick
,onTilesloaded
,onTilt_changed
, andonZoom_changed
events. See Google MapsEvents for more information.
You can control the visibility of the map by using thevisible
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 theGoogle places demo
For example:
<Mapgoogle={this.props.google}visible={false}><Listingplaces={this.state.places}/></Map>
The<Map />
api includes subcomponents intended on being used as children of theMap
component. Any child can be used within theMap
component and will receive the threeprops
(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
To place a marker on the Map, include it as a child of the<Map />
component.
<Mapgoogle={this.props.google}style={{width:'100%',height:'100%',position:'relative'}}className={'map'}zoom={14}><Markertitle={'The marker`s title will appear as a tooltip.'}name={'SOMA'}position={{lat:37.778519,lng:-122.405640}}/><Markername={'Dolores park'}position={{lat:37.759703,lng:-122.428093}}/><Marker/><Markername={'Your position'}position={{lat:37.762391,lng:-122.439192}}icon={{url:"/path/to/custom_icon.png",anchor:newgoogle.maps.Point(32,32),scaledSize:newgoogle.maps.Size(64,64)}}/></Map>
The<Marker />
component accepts aposition
prop that defines the location for theposition
on the map. It can be either a raw object or agoogle.maps.LatLng()
instance.
If noposition
is passed in theprops
, the marker will default to the current position of the map, i.e. themapCenter
prop.
You can also pass any otherprops
you want with the<Marker />
. It will be passed back through marker events.
The marker component can also accept a child InfoMarker component for situations where there is only 1 marker and 1 infowindow.
moveMarker(props,marker,e){console.log(e.latLng.lat(),e.latLng.lng())// get the new coordinates after drag end}
<Markertitle="Location"id={1}position={markerCenter}draggable={true}onDragend={this.moveMarker.bind(this)}><InfoWindowvisible={showInfoWindow}style={styles.infoWindow}><divclassName={classes.infoWindow}><p>Click on the map or drag the marker to select location where the incident occurred</p></div></InfoWindow></Marker>
The<Marker />
component listens for events, similar to the<Map />
component.
You can listen for anonClick
event with the (appropriately named)onClick
prop.
onMarkerClick(props,marker,e){// ..}render(){return(<Mapgoogle={this.props.google}><MarkeronClick={this.onMarkerClick}name={'Current location'}/></Map>)}
You can also pass a callback when the user mouses over a<Marker />
instance by passing theonMouseover
callback:
onMouseoverMarker(props,marker,e){// ..}render(){return(<Mapgoogle={this.props.google}><MarkeronMouseover={this.onMouseoverMarker}name={'Current location'}/></Map>)}
To place a polygon on the Map, set<Polygon />
as child of Map component.
render(){consttriangleCoords=[{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(<Mapgoogle={this.props.google}style={{width:'100%',height:'100%',position:'relative'}}className={'map'}zoom={14}><Polygonpaths={triangleCoords}strokeColor="#0000FF"strokeOpacity={0.8}strokeWeight={2}fillColor="#0000FF"fillOpacity={0.35}/></Map>)}
The<Polygon />
component listens toonClick
,onMouseover
andonMouseout
events.
To place a polyline on the Map, set<Polyline />
as child of Map component.
render(){consttriangleCoords=[{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(<Mapgoogle={this.props.google}style={{width:'100%',height:'100%',position:'relative'}}className={'map'}zoom={14}><Polylinepath={triangleCoords}strokeColor="#0000FF"strokeOpacity={0.8}strokeWeight={2}/></Map>)}
The<Polyline />
component listens toonClick
,onMouseover
andonMouseout
events.
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 avisible
prop. Thevisible
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 aposition
prop or connect the<InfoWindow />
component directly to an existing<Marker />
component by using amarker
prop.
//note: code formatted for ES6 hereexportclassMapContainerextendsComponent{state={showingInfoWindow:false,activeMarker:{},selectedPlace:{},};onMarkerClick=(props,marker,e)=>this.setState({selectedPlace:props,activeMarker:marker,showingInfoWindow:true});onMapClicked=(props)=>{if(this.state.showingInfoWindow){this.setState({showingInfoWindow:false,activeMarker:null})}};render(){return(<Mapgoogle={this.props.google}onClick={this.onMapClicked}><MarkeronClick={this.onMarkerClick}name={'Current location'}/><InfoWindowmarker={this.state.activeMarker}visible={this.state.showingInfoWindow}><div><h1>{this.state.selectedPlace.name}</h1></div></InfoWindow></Map>)}}
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.
<InfoWindowonOpen={this.windowHasOpened}onClose={this.windowHasClosed}visible={this.state.showingInfoWindow}><div><h1>{this.state.selectedPlace.name}</h1></div></InfoWindow>
TheonClose
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 />
.
TheonOpen
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.
To place a circle on the Map, set<Circle />
as child of Map component.
render(){constcoords={lat:-21.805149,lng:-49.0921657};return(<MapinitialCenter={coords}google={this.props.google}style={{width:500,height:500,position:'relative'}}zoom={14}><Circleradius={1200}center={coords}onMouseover={()=>console.log('mouseover')}onClick={()=>console.log('click')}onMouseout={()=>console.log('mouseout')}strokeColor='transparent'strokeOpacity={0}strokeWeight={5}fillColor='#FF0000'fillOpacity={0.2}/></Map>);}
The<Circle />
component listens toonClick
,onMouseover
andonMouseout
events.
TheGoogleApiWrapper
automatically passes thegoogle
instance loaded when the component mounts (and will only load it once).
To set your own custom map style, import your custom map style in JSON format.
constmapStyle=[{featureType:'landscape.man_made',elementType:'geometry.fill',stylers:[{color:'#dceafa'}]},]_mapLoaded(mapProps,map){map.setOptions({styles:mapStyle})}render(){return(<Mapstyle={style}google={this.props.google}zoom={this.state.zoom}initialCenter={this.state.center}onReady={(mapProps,map)=>this._mapLoaded(mapProps,map)}> ...</Map>);}
If you prefer not to use the automatic loading option, you can also pass thewindow.google
instance as aprop
to your<Map />
component.
<Mapgoogle={window.google}/>
If you have some issues, please make an issue on the issues tab and try to include an example. We've had success withhttps://codesandbox.io
An example template might look like:https://codesandbox.io/s/rzwrk2854
git clone https://github.com/fullstackreact/google-maps-react.gitcd google-maps-reactnpm installmake dev
The Google Map React component library uses React and the Google API to give easy access to the Google Maps library.

This Google Map React component library was built alongside the blog postHow to Write a Google Maps React Component.
This repo was written and is maintained by theFullstack React team. In the book we cover many more projects like this. We walk through each line of code, explain why it's there and how it works.
This app is only one of several apps we have in the book. If you're looking to learn React, there's no faster way than by spending a few hours with the Fullstack React book.
About
Companion code to the "How to Write a Google Maps React Component" Tutorial
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.