Skip to main content
The GoogleMap component is the core component of React Google Maps API. It creates and manages a Google Maps instance and provides context for all child components like markers, overlays, and other map features.

Basic Usage

import { GoogleMap, LoadScript } from '@react-google-maps/api'

const containerStyle = {
  width: '100%',
  height: '400px'
}

const center = {
  lat: 37.7749,
  lng: -122.4194
}

function MyMap() {
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        mapContainerStyle={containerStyle}
        center={center}
        zoom={12}
      >
        {/* Add markers, overlays, etc. here */}
      </GoogleMap>
    </LoadScript>
  )
}

Props

Container Props

id
string
HTML element ID for the map container div
mapContainerStyle
CSSProperties
Inline styles for the map container. Must include width and height.
mapContainerStyle={{ width: '100%', height: '400px' }}
mapContainerClassName
string
CSS class name for the map container div

Map Configuration

options
google.maps.MapOptions
Complete Google Maps MapOptions object. This is the most flexible way to configure the map.
options={{
  disableDefaultUI: true,
  zoomControl: true,
  mapTypeControl: false,
  styles: [...] // Custom map styles
}}
center
google.maps.LatLng | google.maps.LatLngLiteral
Map center position. Can be a LatLng object or literal with lat/lng properties.
center={{ lat: 37.7749, lng: -122.4194 }}
zoom
number
Map zoom level (0-22). Higher numbers show more detail.
zoom={12}
heading
number
Map heading in degrees for 45° imagery (0-360)
tilt
number
Map tilt in degrees for 45° imagery (0 or 45)
mapTypeId
string
Map type identifier. Common values:
  • 'roadmap' - Default road map view
  • 'satellite' - Satellite imagery
  • 'hybrid' - Satellite imagery with roads
  • 'terrain' - Terrain elevation data
clickableIcons
boolean
default:"true"
Whether default map POI icons are clickable
streetView
google.maps.StreetViewPanorama
Street View panorama instance to bind to the map
extraMapTypes
google.maps.MapType[]
Additional map types to register with the map

Mouse Events

onClick
(e: google.maps.MapMouseEvent) => void
Fired when the user clicks on the map
onClick={(e) => {
  console.log('Clicked at:', e.latLng?.toJSON())
}}
onDblClick
(e: google.maps.MapMouseEvent) => void
Fired when the user double-clicks on the map
onRightClick
(e: google.maps.MapMouseEvent) => void
Fired when the user right-clicks on the map
onMouseMove
(e: google.maps.MapMouseEvent) => void
Fired when the mouse moves over the map
onMouseOver
(e: google.maps.MapMouseEvent) => void
Fired when the mouse enters the map
onMouseOut
(e: google.maps.MapMouseEvent) => void
Fired when the mouse leaves the map
onMouseDown
(e: google.maps.MapMouseEvent) => void
Fired when the user presses the mouse button on the map
onMouseUp
(e: google.maps.MapMouseEvent) => void
Fired when the user releases the mouse button on the map

Drag Events

onDrag
() => void
Fired repeatedly during map drag
onDragStart
() => void
Fired when drag starts
onDragEnd
() => void
Fired when drag ends

Map Property Change Events

onBoundsChanged
() => void
Fired when the map viewport bounds change
onCenterChanged
() => void
Fired when the map center changes
onZoomChanged
() => void
Fired when the zoom level changes
onMapTypeIdChanged
() => void
Fired when the map type changes
onHeadingChanged
() => void
Fired when the map heading changes
onTiltChanged
() => void
Fired when the map tilt changes
onProjectionChanged
() => void
Fired when the map projection changes

Other Events

onIdle
() => void
Fired when the map becomes idle after panning or zooming
onTilesLoaded
() => void
Fired when the visible tiles have finished loading
onResize
() => void
Fired when the map div changes size

Lifecycle Callbacks

onLoad
(map: google.maps.Map) => void | Promise<void>
Callback invoked when the map is loaded. Receives the map instance.
onLoad={(map) => {
  console.log('Map loaded:', map)
  // Store map instance in ref or state
}}
onUnmount
(map: google.maps.Map) => void | Promise<void>
Callback invoked before the map is unmounted. Receives the map instance.
onUnmount={(map) => {
  console.log('Map unmounting:', map)
  // Cleanup logic here
}}
children
ReactNode
Child components like Marker, Polyline, InfoWindow, etc.

Examples

Controlled Map with State

import { useState } from 'react'
import { GoogleMap, LoadScript } from '@react-google-maps/api'

function ControlledMap() {
  const [center, setCenter] = useState({ lat: 37.7749, lng: -122.4194 })
  const [zoom, setZoom] = useState(12)

  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        mapContainerStyle={{ width: '100%', height: '400px' }}
        center={center}
        zoom={zoom}
        onCenterChanged={() => {
          // Note: Get center from map instance stored in ref
        }}
        onZoomChanged={() => {
          // Note: Get zoom from map instance stored in ref
        }}
      />
    </LoadScript>
  )
}

Accessing Map Instance

import { useRef } from 'react'
import { GoogleMap, LoadScript } from '@react-google-maps/api'

function MapWithInstance() {
  const mapRef = useRef(null)

  const onLoad = (map) => {
    mapRef.current = map
  }

  const handlePanTo = () => {
    if (mapRef.current) {
      mapRef.current.panTo({ lat: 40.7128, lng: -74.0060 })
    }
  }

  return (
    <>
      <button onClick={handlePanTo}>Pan to New York</button>
      <LoadScript googleMapsApiKey="YOUR_API_KEY">
        <GoogleMap
          mapContainerStyle={{ width: '100%', height: '400px' }}
          center={{ lat: 37.7749, lng: -122.4194 }}
          zoom={12}
          onLoad={onLoad}
        />
      </LoadScript>
    </>
  )
}

Custom Map Styling

import { GoogleMap, LoadScript } from '@react-google-maps/api'

const mapStyles = [
  {
    featureType: 'water',
    elementType: 'geometry',
    stylers: [{ color: '#193341' }]
  },
  {
    featureType: 'landscape',
    elementType: 'geometry',
    stylers: [{ color: '#2c5a71' }]
  }
]

function StyledMap() {
  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        mapContainerStyle={{ width: '100%', height: '400px' }}
        center={{ lat: 37.7749, lng: -122.4194 }}
        zoom={12}
        options={{
          styles: mapStyles,
          disableDefaultUI: true,
          zoomControl: true
        }}
      />
    </LoadScript>
  )
}

Handling Click Events

import { useState } from 'react'
import { GoogleMap, Marker, LoadScript } from '@react-google-maps/api'

function InteractiveMap() {
  const [markers, setMarkers] = useState([])

  const handleMapClick = (e) => {
    const newMarker = {
      lat: e.latLng.lat(),
      lng: e.latLng.lng()
    }
    setMarkers([...markers, newMarker])
  }

  return (
    <LoadScript googleMapsApiKey="YOUR_API_KEY">
      <GoogleMap
        mapContainerStyle={{ width: '100%', height: '400px' }}
        center={{ lat: 37.7749, lng: -122.4194 }}
        zoom={12}
        onClick={handleMapClick}
      >
        {markers.map((marker, index) => (
          <Marker key={index} position={marker} />
        ))}
      </GoogleMap>
    </LoadScript>
  )
}

Best Practices

1. Memoize Container Style

Define the container style outside the component or use useMemo to prevent unnecessary re-renders:
const containerStyle = {
  width: '100%',
  height: '400px'
}

// Or inside component:
const containerStyle = useMemo(() => ({
  width: '100%',
  height: '400px'
}), [])

2. Store Map Instance in Ref

Use a ref to store the map instance for programmatic control:
const mapRef = useRef(null)

const onLoad = useCallback((map) => {
  mapRef.current = map
}, [])

3. Use Options Prop for Complex Configuration

For advanced configuration, use the options prop instead of individual props:
const options = useMemo(() => ({
  disableDefaultUI: true,
  zoomControl: true,
  styles: mapStyles,
  gestureHandling: 'cooperative'
}), [])

<GoogleMap options={options} />

4. Debounce Expensive Operations

Debounce callbacks for events that fire frequently like onBoundsChanged or onDrag:
import { useMemo } from 'react'
import debounce from 'lodash/debounce'

const handleBoundsChanged = useMemo(
  () => debounce(() => {
    // Expensive operation
  }, 300),
  []
)

5. Clean Up Event Listeners

The component automatically cleans up all event listeners, but if you add custom listeners via the map instance, clean them up in onUnmount:
const onLoad = (map) => {
  const listener = map.addListener('click', handleClick)
  // Store listener to remove later
}

const onUnmount = (map) => {
  // Remove custom listeners
}

Common Patterns

Responsive Map Container

const containerStyle = {
  width: '100%',
  height: '100vh'
}

// Or with CSS:
// .map-container { width: 100%; height: 100vh; }

<GoogleMap
  mapContainerClassName="map-container"
  center={center}
  zoom={12}
/>

Fitting Bounds to Markers

const onLoad = (map) => {
  const bounds = new window.google.maps.LatLngBounds()
  markers.forEach(marker => {
    bounds.extend(marker.position)
  })
  map.fitBounds(bounds)
}

Map with Multiple Markers

See the Marker component documentation for details on adding multiple markers efficiently.

TypeScript

import { GoogleMap } from '@react-google-maps/api'
import type { GoogleMapProps } from '@react-google-maps/api'

const MyMap: React.FC = () => {
  const handleLoad = (map: google.maps.Map) => {
    console.log('Map loaded:', map)
  }

  const mapOptions: google.maps.MapOptions = {
    disableDefaultUI: true,
    zoomControl: true
  }

  return (
    <GoogleMap
      mapContainerStyle={{ width: '100%', height: '400px' }}
      center={{ lat: 37.7749, lng: -122.4194 }}
      zoom={12}
      options={mapOptions}
      onLoad={handleLoad}
    />
  )
}

LoadScript

Learn how to load the Google Maps API

Marker

Add markers to your map

Build docs developers (and LLMs) love