Integrating Google Maps in React: A Step-by-Step Guide Using Google’s Official Package
While searching online for ways to integrate Google Maps in React, I couldn’t find many detailed articles aside from Google’s official documentation. So, I decided to focus on implementing two key features:
- Retrieving the current location.
- Searching for places, getting suggestions, and extracting results from them.
Steps to follow:
- Google Maps is a paid feature.
- Billing needs to be set up, and then an API key must be generated in the Google Developer Console.
- Go to “Enabled APIs and Services” in the Google Cloud Console and enable the APIs.
- Enable the Places API, Geocoding API, and Maps JavaScript API.
- Package used:
npm install @vis.gl/react-google-maps(recommended by Google).
import { AdvancedMarker, APIProvider, Map } from "@vis.gl/react-google-maps";
function App() {
const position = { lat: 53.54992, lng: 10.00678 };
return (
<APIProvider apiKey={"YOUR API KEY HERE"}>
<Map defaultCenter={position} defaultZoom={10} mapId="DEMO_MAP_ID">
<AdvancedMarker position={position} />
</Map>
</APIProvider>
);
}
export default App;Map components
- Map Component: This controls the display of the Google Map and its settings, such as zoom level and map type.
- Marker: A red pointer that shows a specific location on the map, based on the position attribute you provide.
- Map Control: This feature allows you to add buttons to the map, like “Go to current location”.
- Advanced Marker: Similar to a regular marker, but you can customize it with an image or SVG to suit your design needs.
Setting the current location
- We need to pass the current location to the position attribute of the marker. To get the current location, follow the code below.
useEffect(() => {
//to load your current location on initial reload
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
console.log("geo Location is not supported");
}
function showPosition(position: any) {
setMarkerLocation({
...markerLocation,
lat: position.coords.latitude,
lng: position.coords.longitude,
});
setCenter({
...setCenter,
lat: position.coords.latitude,
lng: position.coords.longitude,
});
}
}, []);Get Manoj L’s stories in your inbox
Join Medium for free to get updates from this writer.
It looks something like this
Panning location to the centre of the map
- The marker should always stay at the center of the map when it is dragged.
- To achieve this, pass the center location to
useEffectas a dependency that updates whenever the location changes.
useEffect(() => {
if (markerRef?.current) {
// Update the map center to start at the initial center
markerRef?.current?.getMap()?.panTo(center);
}
}, [center]);Adding custom button on the map
- You can customize the button using HTML and CSS inside the
<MapControl />component from@vis.gl/react-google-maps. - The “Geocode” API will be used for this functionality.
<Map
defaultZoom={13}
defaultCenter={markerLocation}
gestureHandling={"greedy"}
disableDefaultUI
// onDrag={handleMapDrag}
onIdle={handleIdle}
onDragend={() => {
reverseGeocodeLatLng(markerLocation);
}}
>
<MapControl position={ControlPosition.BOTTOM_RIGHT}>
<div className={styles.current_location} onClick={handleLocationClick}>
<span>
<CurrentLocationSvg />
</span>
<p className="body-sm-secondary">Use current location</p>
</div>
</MapControl>
<Marker ref={markerRef} position={markerLocation} />
</Map>;It looks something like this
Adding functionality to “Go to current location” custom button
- Clicking the button should move both the map and the marker to the current location
const CustomMap = () => {
const maps = useMapsLibrary("geocoding");
const handleLocationClick = () => {
if (navigator.geolocation) {
// console.log(navigator.geolocation.getCurrentPosition(showPosition), "postion")
navigator.geolocation.getCurrentPosition(showPosition);
} else {
// document.getElementById("demo").innerHTML =
// "Geolocation is not supported by this browser.";
console.log("geo Location is not supported");
}
function showPosition(position: any) {
setMarkerLocation({
...markerLocation,
lat: position.coords.latitude,
lng: position.coords.longitude,
});
setCenter({
...setCenter,
lat: position.coords.latitude,
lng: position.coords.longitude,
});
reverseGeocodeLatLng({
lat: position.coords.latitude,
lng: position.coords.longitude,
});
}
};
//Function to perform reverse geocoding
const reverseGeocodeLatLng = async (latLng: any) => {
if (markerRef?.current) {
const newCenter = markerRef?.current?.getMap()?.getCenter();
setMarkerLocation({
lat: newCenter.lat(),
lng: newCenter.lng(),
});
}
if (!maps) return; // Ensure the Geocoder service is available
const geocoder = new maps.Geocoder(); //uncomment before you push
await geocoder.geocode({ location: latLng }, (results: any, status) => {
if (status === "OK" && results.length > 0) {
//your logic
//you can extract complete details of particular location
} else {
console.error("Reverse geocoding failed due to:", status);
}
});
};
return (
<>
<Map
defaultZoom={13}
defaultCenter={markerLocation}
gestureHandling={"greedy"}
disableDefaultUI
// onDrag={handleMapDrag}
onIdle={handleIdle}
onDragend={() => {
reverseGeocodeLatLng(markerLocation);
}}
>
<MapControl position={ControlPosition.BOTTOM_RIGHT}>
<div
className={styles.current_location}
onClick={handleLocationClick}
>
<span>
<CurrentLocationSvg />
</span>
<p className="body-sm-secondary">Use current location</p>
</div>
</MapControl>
<Marker ref={markerRef} position={markerLocation} />
</Map>
;
</>
);
};
export default CustomMap;Adding search Autocomplete
- You can access Google’s search feature using the “Places” API.
- When a user searches for a place, the API returns suggestions based on the search input.
const CustomMap = () => {
const maps = useMapsLibrary("geocoding");
const placeLib = useMapsLibrary("places");
const handleSearchChange = (e: any) => {
setSearchText(e.target.value);
};
useEffect(() => {
if (!maps || !placeLib) return;
const searchPlace = async () => {
//uncomment before you push
if (searchText !== "") {
try {
let x =
await placeLib.AutocompleteSuggestion.fetchAutocompleteSuggestions({
input: searchText,
});
let readableSuggestions = x?.suggestions?.map((suggestion) => {
return {
placeId: suggestion.placePrediction?.placeId || "",
mainText: suggestion.placePrediction?.mainText?.text || "",
secondaryText:
suggestion.placePrediction?.secondaryText?.text || "",
};
});
//apart from placeId, mainText and secondaryText we can take lat and lng
//please check google javascript maps api to get to know more about it
//https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/reference/geocoder#GeocoderResult
console.log(readableSuggestions, "Human-readable suggestions");
} catch (err) {
console.log(err, "error");
}
}
};
searchPlace();
}, [searchText]);
return (
<input
className={styles.searchbox_input}
onChange={handleSearchChange}
type="text"
placeholder="Enter location(eg: area, street, etc)"
value={searchText}
/>
);
};
export default CustomMap;- To extract specific places displayed on the suggestion list, retrieve the
placeIdfrom the suggestions. Then, pass theplaceIdto thereverseGeocodeLatLng()function (from the "Adding functionality to Go to current location" section). Instead of passing alocation, use theplaceIdto get the results and display them on the map.




