Skip to content

Repository files navigation

@stackline/react-google-maps

A maintained React 19 wrapper for Google Maps with declarative maps, markers, advanced markers, clustering, overlays, directions, geocoding hooks, and versioned live demos.

npm version npm downloads license React 19 Google Maps

Documentation & Live Demos | npm | Issues | Repository

Latest version: 19.0.0

Why this library?

@stackline/react-google-maps is built for teams that want the same clarity people liked in the Angular Google Maps package, but in React:

  • a single provider that loads the Google Maps JavaScript API once
  • a declarative <GoogleMap> shell with familiar props like center, zoom, mapId, and options
  • component wrappers for markers, advanced markers, info windows, overlays, layers, controls, and directions
  • hooks for service-style flows like geocoding
  • official marker clustering support through @googlemaps/markerclusterer

The result is intentionally migration-friendly. A complex Angular or imperative Google Maps codebase can usually move over one feature at a time without giving up access to the native map instances.

Extension-friendly by design

This package is not a "locked box" wrapper. The components are meant to stay declarative for common usage, while still giving you the same escape hatches teams rely on in Angular:

  • ref handles on GoogleMap, MapMarker, MapInfoWindow, MapMarkerClusterer, MapPolyline, MapPolygon, MapRectangle, MapCircle, MapGroundOverlay, and MapDirectionsRenderer
  • onLoad callbacks that expose the native Google Maps instances directly
  • useGoogleMap() to access the current native google.maps.Map from nested React components
  • useMapGeocoder() and useDirectionsService() for service-style integrations

That means you can keep a typed React API for the 90% case and still drop to native Google Maps methods when a complex application needs something custom.

React Version Compatibility

Each package family only installs on its matching React family. Framework major and package major are not always the same package number, so use the package family column below.

Package family Framework family Peer range Tested release window Demo link
19.x React 19 only >=19.0.0 <20.0.0 19.0.0 -> 19.2.5 React 19 family docs
18.x React 18 only >=18.0.0 <19.0.0 18.0.0 -> 18.3.1 React 18 family docs
17.x React 17 only >=17.0.0 <18.0.0 17.0.0 -> 17.0.2 React 17 family docs

Installation

npm install @stackline/react-google-maps

Choose the package family from the compatibility table above. Each published family is locked to one framework major only.

Basic Usage

import {
  GoogleMap,
  GoogleMapsProvider,
  MapMarker
} from '@stackline/react-google-maps';

const center = { lat: 40.7128, lng: -74.006 };

export function App() {
  return (
    <GoogleMapsProvider apiKey={import.meta.env.VITE_GOOGLE_MAPS_API_KEY} mapIds={['DEMO_MAP_ID']}>
      <GoogleMap center={center} zoom={11} height={420}>
        <MapMarker position={center} title="New York City" />
      </GoogleMap>
    </GoogleMapsProvider>
  );
}

Advanced Markers

import {
  GoogleMap,
  GoogleMapsProvider,
  MapAdvancedMarker
} from '@stackline/react-google-maps';

export function CapitalMap() {
  return (
    <GoogleMapsProvider apiKey={import.meta.env.VITE_GOOGLE_MAPS_API_KEY} mapIds={['DEMO_MAP_ID']}>
      <GoogleMap center={{ lat: 45.4215, lng: -75.6972 }} zoom={6} mapId="DEMO_MAP_ID" height={420}>
        <MapAdvancedMarker position={{ lat: 45.4215, lng: -75.6972 }}>
          <div style={{ padding: 12, borderRadius: 12, background: 'white' }}>
            <strong>Ottawa</strong>
            <div>Advanced marker content</div>
          </div>
        </MapAdvancedMarker>
      </GoogleMap>
    </GoogleMapsProvider>
  );
}

Marker Clustering

import {
  createClusterRenderer,
  GoogleMap,
  GoogleMapsProvider,
  MapAdvancedMarker,
  MapMarker,
  MapMarkerClusterer
} from '@stackline/react-google-maps';

const points = [
  { lat: 37.782, lng: -122.447 },
  { lat: 37.789, lng: -122.405 },
  { lat: 37.766, lng: -122.438 }
];

export function ClusteredMap() {
  return (
    <GoogleMapsProvider apiKey={import.meta.env.VITE_GOOGLE_MAPS_API_KEY}>
      <GoogleMap center={{ lat: 37.7749, lng: -122.4194 }} zoom={10} height={420}>
        <MapMarkerClusterer>
          {points.map((point, index) => (
            <MapMarker key={index} position={point} />
          ))}
        </MapMarkerClusterer>
      </GoogleMap>
    </GoogleMapsProvider>
  );
}

If you need branded cluster visuals, the wrapper also exposes a helper for HTML or advanced-marker-based cluster rendering:

const renderer = createClusterRenderer({
  render: ({ count }) => {
    const element = document.createElement('div');
    element.className = 'cluster-card';
    element.innerHTML = `<strong>${count}</strong><span>places</span>`;
    return element;
  }
});

<MapMarkerClusterer renderer={renderer}>
  <MapAdvancedMarker position={point}>...</MapAdvancedMarker>
</MapMarkerClusterer>

Directions

import { useState } from 'react';
import {
  GoogleMap,
  GoogleMapsProvider,
  MapDirectionsRenderer,
  MapDirectionsService
} from '@stackline/react-google-maps';

export function DirectionsDemo() {
  const [directions, setDirections] = useState<google.maps.DirectionsResult | null>(null);

  return (
    <GoogleMapsProvider apiKey={import.meta.env.VITE_GOOGLE_MAPS_API_KEY}>
      <GoogleMap center={{ lat: 45.4215, lng: -75.6972 }} zoom={6} height={420}>
        <MapDirectionsService
          request={{
            origin: 'Toronto, ON',
            destination: 'Montreal, QC',
            travelMode: 'DRIVING' as google.maps.TravelMode
          }}
          onResult={({ result }) => setDirections(result ?? null)}
        />
        <MapDirectionsRenderer directions={directions} />
      </GoogleMap>
    </GoogleMapsProvider>
  );
}

Geocoding Hook

import { useState } from 'react';
import {
  GoogleMap,
  GoogleMapsProvider,
  MapMarker,
  useMapGeocoder
} from '@stackline/react-google-maps';

function GeocoderInner() {
  const geocoder = useMapGeocoder();
  const [center, setCenter] = useState({ lat: 43.6532, lng: -79.3832 });

  async function geocodeAddress() {
    const response = await geocoder?.geocode({ address: 'Toronto City Hall' });
    const first = response?.results[0];
    if (first?.geometry.location) {
      setCenter(first.geometry.location.toJSON());
    }
  }

  return (
    <>
      <button onClick={geocodeAddress}>Geocode</button>
      <GoogleMap center={center} zoom={14} height={420}>
        <MapMarker position={center} />
      </GoogleMap>
    </>
  );
}

export function GeocoderDemo() {
  return (
    <GoogleMapsProvider apiKey={import.meta.env.VITE_GOOGLE_MAPS_API_KEY}>
      <GeocoderInner />
    </GoogleMapsProvider>
  );
}

Main API

Surface Notes
GoogleMapsProvider Loads the API once and shares readiness through context.
GoogleMap Creates the native google.maps.Map and supports refs for imperative access.
MapMarker Thin wrapper around google.maps.Marker.
MapAdvancedMarker Thin wrapper around google.maps.marker.AdvancedMarkerElement.
MapInfoWindow Declarative info window with React content via portal.
MapMarkerClusterer Official clustering through @googlemaps/markerclusterer.
MapPolyline, MapPolygon, MapRectangle, MapCircle Declarative shape overlays.
MapGroundOverlay, MapKmlLayer, MapHeatmapLayer Common overlays and layers.
MapTrafficLayer, MapTransitLayer, MapBicyclingLayer Built-in transportation layers.
MapDirectionsService, MapDirectionsRenderer Declarative routing request + display flow.
useMapGeocoder() Memoized geocoder hook.
useDirectionsService() Memoized directions service hook.
useGoogleMap() Access the native google.maps.Map from nested components.
MapControl Mount React UI inside native map control positions.

Docs Coverage

The live docs are intentionally rich and mirror the kinds of workflows developers look for in the official Google Maps documentation:

  • basic map bootstrapping
  • controlled center and zoom
  • click events
  • markers and info windows
  • advanced markers
  • draggable markers
  • marker clustering
  • polylines, polygons, rectangles, circles
  • ground overlays
  • traffic, transit, and bicycling layers
  • KML layers
  • heatmaps
  • directions
  • geocoding
  • custom map controls

Changelog

19.0.0

  • Initial React 19 line
  • Added versioned docs for React 17, 18, and 19
  • Added declarative wrappers for maps, markers, advanced markers, clustering, shapes, layers, directions, and geocoding

18.0.0

  • React 18 compatibility line

17.0.0

  • React 17 compatibility line

Security

Report vulnerabilities privately by following SECURITY.md. Do not disclose exploit details in a public issue.

License

Licensed under the MIT License. See LICENSE.

About

Maintained React 18 and 19 wrapper for Google Maps JavaScript API with typed components, hooks, clustering and services.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages