Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@vis.gl/react-google-maps": "1.8.3",
"dotenv": "^17.4.2",
"react": "^19.2.8",
"react-dom": "^19.2.7"
"react-dom": "^19.2.8"
},
"overrides": {
"fast-xml-parser": "5.7.1",
Expand Down
125 changes: 125 additions & 0 deletions samples/new-react-sample.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#!/bin/bash

# A script to generate boilerplate for a new Google Maps React sample.
# Usage: ./new-react-sample.sh <sample-name>

if [ -z "$1" ]; then
echo "Usage: $0 <sample-name>"
exit 1
fi

NAME=$1
# Replace hyphens with underscores for the region tag
REGION_TAG="maps_${NAME//-/_}"
TITLE="React - ${NAME//-/ }"

# Create the directory
mkdir -p "$NAME/src"

# Create src/app.tsx
cat > "$NAME/src/app.tsx" << EOF
/**
* @license
* Copyright 2026 Google LLC. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

// [START ${REGION_TAG}_app]
import React from 'react';
import { createRoot } from 'react-dom/client';
import { APIProvider, Map } from '@vis.gl/react-google-maps';

const API_KEY = 'GOOGLE_MAPS_API_KEY';

export default function App() {
return (
<APIProvider apiKey={API_KEY}>
<Map
defaultCenter={{ lat: 37.422, lng: -122.084 }}
defaultZoom={14}
mapId="DEMO_MAP_ID"
>
{/* Add map components here */}
</Map>
</APIProvider>
);
}

export function renderToDom(container: HTMLElement) {
const root = createRoot(container);
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
}
// [END ${REGION_TAG}_app]
EOF

# Create index.html
cat > "$NAME/index.html" << EOF
<!doctype html>
<!--
@license
Copyright 2026 Google LLC. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
-->
<!-- [START $REGION_TAG] -->
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<title>$TITLE</title>
<style>
body {
margin: 0;
font-family: sans-serif;
}
#app {
width: 100vw;
height: 100vh;
}
</style>
<script type="module">
import { renderToDom } from './src/app';

renderToDom(document.querySelector('#app'));
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
<!-- [END $REGION_TAG] -->
EOF

# Create package.json
cat > "$NAME/package.json" << EOF
{
"name": "@js-api-samples/$NAME",
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "bash ../build-single.sh",
"test": "tsc && npm run build:vite --workspace=.",
"start": "tsc && vite build --config ../../vite.config.js --base './' && vite --config ../../vite.config.js",
"build:vite": "vite build --config ../../vite.config.js --base './'",
"preview": "vite preview --config ../../vite.config.js"
},
"author": "Google LLC"
}
EOF

# Create tsconfig.json
cat > "$NAME/tsconfig.json" << EOF
{
"extends": "../../tsconfig.react-base.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["./src/**/*.ts*"]
}
EOF

echo "Created React sample '$NAME' successfully!"
70 changes: 70 additions & 0 deletions samples/rgm-autocomplete/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Google Maps JavaScript Sample

## rgm-autocomplete

React Google Maps Library - Place Autocomplete

This sample demonstrates using the Place Autocomplete Element within a React application using the open source vis.gl/react-google-maps library.

## Setup

### Before starting run:

`npm i`

### Run an example on a local web server

`cd samples/rgm-autocomplete`
`npm start`

### Build an individual example

`cd samples/rgm-autocomplete`
`npm run build`

From 'samples':

`npm run build --workspace=rgm-autocomplete/`

### Build all of the examples.

From 'samples':

`npm run build-all`

### Run lint to check for problems

`cd samples/rgm-autocomplete`
`npx eslint index.ts`

## Feedback

For feedback related to this sample, please open a new issue on
[GitHub](https://github.com/googlemaps-samples/js-api-samples/issues).

## Integrating Place Autocomplete & The New Place Class

When integrating Google Maps Place Autocomplete within a React application, this sample implements several key best practices and addresses common issues developers encounter with the new Places API.

### 1. Programmatic Instantiation

Instead of rendering the `<gmp-place-autocomplete>` Web Component directly in JSX, this sample programmatically instantiates it using `new placesLibrary.PlaceAutocompleteElement()` and appends it to a React `ref`.

- **Issue:** React's synthetic event system doesn't always seamlessly handle custom Web Component events (like `gmp-select`). Instantiating the element programmatically and attaching standard DOM event listeners ensures events are captured reliably.

### 2. Location Restriction & Cross-Context Objects

When placing the autocomplete Web Component outside the main DOM tree of the map, it may lose automatic context of the map's viewport. To guarantee that search predictions are strictly biased or restricted to the map's current bounds, this sample manually syncs the map's bounds to the autocomplete's `locationRestriction` property.

- **Issue:** Passing complex Google Maps objects (like `LatLngBounds`) directly across the React boundary can sometimes fail due to cross-context `instanceof` checks. Always use `.toJSON()` (e.g., `map.getBounds().toJSON()`) when assigning bounds to bypass these issues. This ensures users see search predictions relevant to their map view.

### 3. Handling Selections: `toPlace()` and `fetchFields()`

When a user selects an item from the autocomplete dropdown, the component fires a `gmp-select` event containing a `placePrediction`.

- **Issue:** The prediction is _not_ a fully populated Place object. You must convert it using `placePrediction.toPlace()` and then explicitly request the data you need by calling `place.fetchFields({ fields: ['location', 'displayName', 'formattedAddress'] })`.
- If you attempt to access a property on the `Place` object that hasn't been fetched, it will be undefined or throw an error. This is a core design principle of the new Places API to ensure you only request (and pay for) the data you use.

### 4. Event Cleanup

Always remove standard DOM event listeners (e.g., `autocomplete.removeEventListener`) and Maps event listeners (`google.maps.event.removeListener`) in your `useEffect` cleanup function to prevent memory leaks when the React component unmounts.
35 changes: 35 additions & 0 deletions samples/rgm-autocomplete/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!doctype html>
<!--
@license
Copyright 2026 Google LLC. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
-->
<!-- [START maps_react_place_autocomplete_map] -->
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no" />
<title>React - react place autocomplete map</title>
<style>
body {
margin: 0;
font-family: sans-serif;
}
#app {
width: 100vw;
height: 100vh;
}
</style>
<script type="module">
import { renderToDom } from './src/app';

renderToDom(document.querySelector('#app'));
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
<!-- [END maps_react_place_autocomplete_map] -->
13 changes: 13 additions & 0 deletions samples/rgm-autocomplete/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "@js-api-samples/rgm-autocomplete",
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "bash ../build-single.sh",
"test": "tsc && npm run build:vite --workspace=.",
"start": "tsc && vite build --config ../../vite.config.js --base './' && vite --config ../../vite.config.js",
"build:vite": "vite build --config ../../vite.config.js --base './'",
"preview": "vite preview --config ../../vite.config.js"
},
"author": "Google LLC"
}
Loading
Loading