Published Sep 16, 2025 ⦁ Updated Oct 11, 2026 ⦁ 6 min read

React Google Maps: Use the Google Maps API in React

The simplest way to use Google Maps in React today is @vis.gl/react-google-maps, a library of React components and hooks for the Maps JavaScript API. The Google Maps Platform team started it, and Google's own React page lists it. You wrap your app in <APIProvider apiKey=...>, render a <Map>, and add <AdvancedMarker>, <InfoWindow> and Places Autocomplete as children. Below is a setup that works with React 18 and 19, Vite or Next.js, as of October 2026 (library version 1.10).

Which React Google Maps library should you use?

Search "react google maps" on npm and you get several packages with nearly the same name. Here's where they stand:

Package Status (October 2026) Use it?
@vis.gl/react-google-maps Active, v1.10.x, started by the Google Maps Platform team (docs) Yes, for new projects
@react-google-maps/api Community library, v2.20.x, last published December 2025 OK for existing apps; it predates Advanced Markers and the new Places widgets
google-map-react v2.2.x, last published May 2025, renders React components over a map Legacy projects only
react-google-maps (tomchentw) Abandoned for years (v9.4.5) No
@googlemaps/react-wrapper Google's thin loader: loads the script, you write imperative code Only if you want raw google.maps calls

The rest of this guide uses @vis.gl/react-google-maps. Its components wrap the current Maps JavaScript API objects (AdvancedMarkerElement, importLibrary), so it follows what Google recommends today. The old google.maps.Marker is deprecated, for example.

Step 1: Get a Google Maps API key

  1. In the Google Cloud console, create or pick a project and attach a billing account. The Maps JavaScript API won't load without one, even if you stay inside the free usage.
  2. Go to APIs & Services > Library and enable Maps JavaScript API. For autocomplete, also enable Places API (New).
  3. Go to Keys & Credentials (or APIs & Services > Credentials) and create an API key.
  4. Restrict the key. Under application restrictions pick Websites and add your domains (http://localhost:5173/*, https://yourapp.com/*). Under API restrictions allow only the APIs you enabled. A browser key is always visible to visitors, so these restrictions are your only protection (API security best practices).
  5. For markers you also need a Map ID (see step 4). Use DEMO_MAP_ID while testing; Google allows it for that (Advanced Markers docs).

Put the key in an env file, not in source control:

# Vite: .env.local
VITE_GOOGLE_MAPS_API_KEY=your-key-here

# Next.js: .env.local
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY=your-key-here

Step 2: Install the library

npm install @vis.gl/react-google-maps

It works with React 16.8 and up, including React 19, and pulls in the @types/google.maps types, so TypeScript works without extra setup.

Step 3: Render a map in React

import {APIProvider, Map} from '@vis.gl/react-google-maps';

const API_KEY = import.meta.env.VITE_GOOGLE_MAPS_API_KEY as string;

export default function App() {
  return (
    <APIProvider apiKey={API_KEY}>
      <div style={{height: '100vh', width: '100%'}}>
        <Map
          defaultCenter={{lat: 40.7128, lng: -74.006}}
          defaultZoom={12}
          gestureHandling="greedy"
          disableDefaultUI
        />
      </div>
    </APIProvider>
  );
}

Three things trip people up:

  • The map needs a height. A Google map's natural height is 0. <Map> fills its parent (width: 100%; height: 100%), so the parent must have a size (Map docs).
  • defaultCenter vs center. defaultCenter/defaultZoom set the start position and let the user pan freely. center/zoom are controlled props: if you pass them without updating state in onCameraChanged, the map snaps back after every drag.
  • One APIProvider. Put it high in the tree, once. It loads the script a single time and every map and hook below it shares it.

In Next.js (App Router), the map is client-only. Put it in a file that starts with 'use client' and read the key from process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY.

Step 4: Add markers with AdvancedMarker

AdvancedMarker wraps Google's AdvancedMarkerElement. It only works on a map that has a mapId (AdvancedMarker docs). Create a real Map ID in the console under Map management before production.

import {APIProvider, Map, AdvancedMarker, Pin} from '@vis.gl/react-google-maps';

const offices = [
  {id: 'nyc', name: 'New York', position: {lat: 40.7128, lng: -74.006}},
  {id: 'bos', name: 'Boston', position: {lat: 42.3601, lng: -71.0589}},
];

export function OfficeMap() {
  return (
    <APIProvider apiKey={import.meta.env.VITE_GOOGLE_MAPS_API_KEY}>
      <div style={{height: 500}}>
        <Map mapId="DEMO_MAP_ID" defaultCenter={{lat: 41.5, lng: -73}} defaultZoom={7}>
          {offices.map(o => (
            <AdvancedMarker key={o.id} position={o.position} title={o.name}>
              <Pin background="#0f9d58" borderColor="#006425" glyphColor="#ffffff" />
            </AdvancedMarker>
          ))}
        </Map>
      </div>
    </APIProvider>
  );
}

Leave out <Pin> to get the default red marker, or pass any JSX (an <img>, a styled <div>) as children for a fully custom marker. For hundreds of markers, cluster them with @googlemaps/markerclusterer; the library's examples show how.

Step 5: Show an InfoWindow when a marker is clicked

Connect an InfoWindow to a marker with useAdvancedMarkerRef. Listen to onClose too, because the user can close the window with its built-in X, and your state needs to know about it (InfoWindow docs).

import {useState} from 'react';
import {AdvancedMarker, InfoWindow, useAdvancedMarkerRef} from '@vis.gl/react-google-maps';

export function MarkerWithInfo({position, name}: {position: google.maps.LatLngLiteral; name: string}) {
  const [markerRef, marker] = useAdvancedMarkerRef();
  const [open, setOpen] = useState(false);

  return (
    <>
      <AdvancedMarker ref={markerRef} position={position} onClick={() => setOpen(o => !o)} />
      {open && (
        <InfoWindow anchor={marker} onClose={() => setOpen(false)}>
          <strong>{name}</strong>
        </InfoWindow>
      )}
    </>
  );
}

Step 6: Places Autocomplete in React

Since March 1, 2025, the legacy google.maps.places.Autocomplete widget isn't available to new Google Cloud projects; Google moved it to legacy status. Use the new PlaceAutocompleteElement (docs). The library has no wrapper component for it, but useMapsLibrary('places') loads the Places library for you:

import {useEffect, useRef} from 'react';
import {useMap, useMapsLibrary} from '@vis.gl/react-google-maps';

export function PlaceSearch() {
  const map = useMap();
  const places = useMapsLibrary('places');
  const container = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!places || !map || !container.current) return;

    const input = new places.PlaceAutocompleteElement({includedRegionCodes: ['us']});
    const onSelect = async (event: Event) => {
      const {placePrediction} = event as google.maps.places.PlacePredictionSelectEvent;
      const place = placePrediction.toPlace();
      await place.fetchFields({fields: ['displayName', 'formattedAddress', 'location']});
      if (place.location) {
        map.panTo(place.location);
        map.setZoom(15);
      }
    };

    input.addEventListener('gmp-select', onSelect);
    container.current.appendChild(input);
    return () => {
      input.removeEventListener('gmp-select', onSelect);
      input.remove();
    };
  }, [places, map]);

  return <div ref={container} />;
}

Render <PlaceSearch /> inside <APIProvider> and next to (or inside) a <Map>, so useMap() finds the map. Ask fetchFields only for the fields you need, because the fields you request decide which Places SKU you're billed for.

What the Google Maps API costs in a React app

The library is free; Google bills the API calls. On March 1, 2025, Google replaced the old $200 monthly credit with free usage per SKU (March 2025 changes). As of October 2026 (pricing):

SKU Free per month Then (per 1,000)
Dynamic Maps (each map load) 10,000 $7.00
Autocomplete Requests 10,000 $2.83
Place Details Essentials 10,000 $5.00
Maps Embed API (iframe) Unlimited Free

Ways to keep the bill down in React:

  • Don't re-create maps. Every new google.maps.Map counts as a map load. If a map mounts and unmounts as users switch routes, add the reuseMaps prop to <Map> so instances get reused.
  • Debounce your own search inputs if you call autocomplete services directly. The widget handles session tokens for you.
  • Set quotas and budget alerts in the Cloud console so a leaked key or a render loop can't run up a big bill.
  • Use an iframe (Maps Embed API) if all you need is a static location map. It's free and needs no JS.

If Google's pricing doesn't fit, compare it with OpenStreetMap-based providers in DevHunt's list of free maps and geocoding APIs. For the plain-JavaScript side (geocoding, directions, Places web services), see our Google Maps API integration basics.

Common errors

  • Blank grey area: the container has no height, or the key's website restriction doesn't include the current origin. Check the browser console for RefererNotAllowedMapError.
  • ApiNotActivatedMapError: enable Maps JavaScript API (or Places API (New)) in the same project as the key.
  • Markers don't show: AdvancedMarker without a mapId on the <Map>.
  • "This page can't load Google Maps correctly": billing isn't enabled on the project.
  • Map jumps back after dragging: you passed controlled center/zoom without an onCameraChanged handler. Use defaultCenter/defaultZoom instead.

More React tutorials that use free APIs: choosing an API for a React weather app, or browse API tools on DevHunt.

FAQ

What is the best React Google Maps library?

For new projects, @vis.gl/react-google-maps. The Google Maps Platform team started it, it supports Advanced Markers and the newer libraries through useMapsLibrary, and it's actively released. @react-google-maps/api still works and is widely used in older code.

Is react-google-maps free?

The npm packages are free and open source. The Google Maps API behind them is paid per use, with free usage per SKU each month (10,000 map loads on Dynamic Maps as of October 2026), and you need a billing account on the project.

How do I use the Google Maps API in React with TypeScript?

Install @vis.gl/react-google-maps. It includes the @types/google.maps types, so google.maps.LatLngLiteral, google.maps.places.Place and the rest are available globally. All examples in this guide are TSX.

Why do I need a Map ID?

Advanced Markers and cloud-based map styling only work on maps with a Map ID. Use DEMO_MAP_ID for testing, then create one in the Cloud console under Map management. You can style that Map ID in the console without changing code.

Can I use Google Maps in React Native?

Not with these libraries; they target the browser DOM. React Native apps usually use react-native-maps, which wraps the native Google Maps SDK on Android (and Apple Maps or Google Maps on iOS).