Hello everyone, I hope you are doing.
today I would like to explain how to use google maps places autocomplete without any libraries or npm's packages and headache π so that let's get started
Setup and Installing React JS
let's do it very quick just follow the steps I suppose you have some background how to do so
3.
4.
5.
6.
the first thing you have to do in index.html after setup the project is that
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title> React js with Google Map AutoComplete </title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
** <script
src="https://maps.googleapis.com/maps/api/js?key="your-api-key"&libraries=places&callback=initMap"
async
></script>**
</body>
</html>
after that create a component for Map using the library @react-google-maps/api
import React, { useState, useCallback } from 'react'
import { GoogleMap, Marker, useJsApiLoader } from '@react-google-maps/api'
const mapStyle = {
height: '300px',
width: '100%'
}
const Map = () => {
const DEFAULT_ZOOM = 5
const { isLoaded } = useJsApiLoader({
id: 'google-map-script',
googleMapsApiKey: "your-api-key"
})
const [map, setMap] = React.useState(null)
const [markerPosition, setMarkerPosition] = useState({
lat: 28.0289837,
lng: 1.6666663,
})
const [defaultLocation, setDefaultLocation] = useState({
lat: 28.0289837,
lng: 1.6666663,
})
const onLoad = useCallback((map)=> {
const bounds = new window.google.maps.LatLngBounds({
lat: 28.0289837,
lng: 1.6666663,
});
map.fitBounds(bounds);
setMap(map)
}, [])
const onUnmount = useCallback(() =>{
setMap(null)
}, [])
const handelClickOnMap = ()=> {
}
return (
<div>
{
isLoaded ? (
<GoogleMap
onLoad={onLoad}
center={defaultLocation}
zoom={DEFAULT_ZOOM}
mapContainerStyle={mapStyle}
onClick={handelClickOnMap}
onUnmount={onUnmount}
>
<Marker position={markerPosition} />
</GoogleMap>
) : <></>
}
</div>
)
}
export default Map
after that import Map component in App.jsx file
and now let's create our input for search for places with autocomplete (suggestion places)
import { useRef, useState } from 'react'
import MapView from './components/Map'
function App() {
const inputRef = useRef()
const inputStyle= {
boxShadow: 'inset 0 0 10px #eee !important',
border: '2px solid #eee',
width: '456px',
height: '40px',
marginLeft: '16px',
borderRadius: '20px',
fontWeight: '300 !important',
outline: 'none',
padding: '10px 20px',
marginBottom: '10px',
}
const autoComplete = new window.google.maps.places.Autocomplete(
inputRef.current,
)
autoComplete.addListener('place_changed', () => {
const place = autoComplete.getPlace()
if (!place.geometry || !place.geometry.location) {
// User entered the name of a Place that was not suggested and
// pressed the Enter key, or the Place Details request failed.
alert("this location not available")
}
if (place.geometry.viewport || place.geometry.location) {
// do something
console.log(place.geometry.location)
}
})
return (
<div className="App">
<label >Location</label>
<input
placeholder='type your location'
ref={inputRef}
style={inputStyle}
/>
<MapView/>
</div>
)
}
export default App
and voila here it is the result π
Finally, Thank you for reading this post I will glad to hear your feedback.
Github repo for code source
https://github.com/abdeldjalilhachimi/react-google-map-autocomplete
Top comments (7)
Hi,
thank you for your post, this has saved me many hours of work!
I have copy-pasted your code and it seems to be working fine, but I can see that too many requests are send when I type someting in the autocomplete imput:
For example, if I want to find "fuente" (fountain, in Spanish), I type an F, then a U, then a E etc... Only with 4-5 characters I can see 150 requests to the API. Do you know how to fix that?
Thanks!
@boira Well in this case you can use debounce to delay sending a request when the user typing and that's it
Hi,
and how can I use that? I haven't found any parameter or way to add that in your example or in the repo.
Thank you very much for your help :-)
@boira
well first of all
install debounce ==> npm install debounce
and users like this in code
.....
import debounce from 'debounce';
const handlePlaceChanged = debounce(() => {
const place = autoComplete.getPlace();
if (!place.geometry || !place.geometry.location) {
/// do some stuff based on what you want
}
if (place.geometry.viewport || place.geometry.location) {
// do something
console.log(place.geometry.location);
}
}, 500); // Adjust the delay (in milliseconds) according to your needs
autoComplete.addListener('place_changed', handlePlaceChanged);
Hi,
I see, thanks :-).
I will try this approach and see. Nevertheless, I think that the problem is not appearing when getting the place details, but when users types things in the autocomplete input.
Eerytime that a user types a character in the input, many (20, 50...) requests to maps.googleapis.com/maps/api/place... are sent. After those requests, I can see the options to choose and when I click one of them the call to PlaceService.GetPlaceDetails (only one, this is good) is done.
I'll test this approach and investigate deeper. I am a backend developer so React is being a bit hard to understand. But I am very pleased with your help and ideas.
Keep in touch!
Hello, thanks for this tutorial but I am having a major issue even though I wrote my code exactly as you taught. so after the process, the input field showed on the screen but when I try to search for a place I don't see an auto-complete plus on the map I am just getting a blank view. I also cloned your code from GitHub and I am getting the same issue. I used my google API key so my google API key might be the issue but I can see some errors and warnings in my console, I will paste them here maybe it will help give you a better context of my issue
"InvalidValueError: not an instance of HTMLInputElement"
"Google Maps already loaded outside @googlemaps/js-api-loader.This may result in undesirable behavior as options and script parameters may not match." - this is a warning in my console
"Source map error: No sources are declared in this source map.
Resource URL: localhost:5173/node_modules/.vite/...
Source Map URL: react.js.map" - another warning in my console
"Source map error: JSON.parse: unexpected character at line 1 column 1 of the JSON data
Resource URL: null
Source Map URL: react_devtools_backend_compact.js.map"
above is how the map field is showing and it does not display a map
same here