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