Creating a Smart Address Search with Google Maps API and React
Google provides robust access to its Maps API, which can be leveraged for various location-based functionalities and map-related tasks. In this article, I will explain how we utilized the Google AutocompleteService API to build a Smart Address Search field that replaces a full address form.
By using this approach, we reduced user input errors and improved the user experience by simplifying the address entry process, making it quicker and more accurate (1 smart input vs 3, huh).
Step 1: Google Maps API Setup in React
First of all, to work with the Maps API you will need to enable it in Google Maps Platform and get the API key.
In our project, we use @react-google-maps/api package (npm i @react-google-maps/api).
Let's initialize the SDK with the custom useGoogleMapsApi hook, to make it reusable within the application:
const useGoogleMapsApi = () => { const api = useJsApiLoader({ id: "app", googleMapsApiKey: "", // set your Public key }); return { ...api, }; };
Step 2: Place Search with Google Autocomplete
Places Autocomplete Service provides an API to search within the places. It provides 2 methods:
- getQueryPredictions() returns results, that do not necessary have the "place_id". It might also include search terms or groups of places like restaurants.
- getPlacePredictions() returns precise places and administrative entities.
To implement our search, we used the getPlacePredictions() method. Let's add this method to our code and return it from the hook.
// Function to search for places using Google Autocomplete Service const searchPlaces = async ( query: string, options?: Omit<google.maps.places.AutocompletionRequest, "input"> ): Promise<Array<google.maps.places.AutocompletePrediction>> => { // Load AutocompleteService from Google Maps API const { AutocompleteService } = (await google.maps.importLibrary( "places" )) as google.maps.PlacesLibrary; const autocomplete = new AutocompleteService(); try { // Fetch place predictions based on user query const { predictions } = await autocomplete.getPlacePredictions({ ...options, // Optional additional parameters for more precise searches input: query, // User's search query (e.g., "Baker Street") }); // Return the list of predictions to display to the user return predictions; } catch { // If there's an error, return an empty array return []; } };
AutocompletionRequest interface uses the input field as a search query and other options, which allows to make a search more accurate. We will talk about them later.
We will use a simple input and a list of results for our demo.
import useGoogleMapsApi from "./useGoogleMapsApi"; import { useEffect, useState } from "react"; export default function App() { const { searchPlaces } = useGoogleMapsApi(); // State to store input value from the user const [inputValue, setInputValue] = useState<string>(""); // State to store the list of place predictions from Google Autocomplete const [places, setPlaces] = useState< Array<google.maps.places.AutocompletePrediction> >([]); // Function to handle the search process when the user types a query const handleSearch = async (searchQuery: string) => { const result = await searchPlaces(searchQuery); setPlaces(result); }; // Trigger the search whenever the input value changes useEffect(() => { handleSearch(inputValue); }, [inputValue]); return ( <div style={{ maxWidth: "80%", width: "100%",fontFamily: "sans-serif",}}> <input value={inputValue} onChange={(e) => setInputValue(e.target.value)} placeholder="Find an address" /> {places.map((place) => ( <div style={{ marginBottom: "0.5rem",}}> <span style={{ color: "blue", cursor: "pointer",}}> {place.description} </span> <span style={{ color: "#333", fontSize: "0.75rem",}}>{`(${place.place_id})`}</span> <span> - {place.types.join(", ")}</span> </div> ))} </div> ); }
From the predictions, we are interested in the 3 fields:
- Place full name.
- Place id.
- Place types - the array of types the entity belongs to. You can find a full list of types here. We use them for the additional results filtering.
Step 3: Refining Autocomplete Results
AutocompleteService interface has a bunch of inputs, that allow make a search more accurate.
Field componentRestrictions allows us to narrow the search results to one specific country. It supports up to 5 countries and requires country codes to be in ISO 3166-1 Alpha-2 standard. Here you can find a list of countries' codes.
const { predictions } = await autocomplete.getPlacePredictions({ ...options, input: query, componentRestrictions: { country: ["gb"], }, });
To make our field not confusing for the users, we need to exclude places like parks, airports, etc from the search results. The Autocomplete service has a field types to specify the types of predictions to be returned. But only one type is allowed for the AutocompleteService.
const { predictions } = await autocomplete.getPlacePredictions({ ...options, input: query, componentRestrictions: { country: ["gb"], }, types: ["geocode"], });
- geocode type instructs the Place Autocomplete service to return only geocoding results, rather than business results.
But it also includes the bigger administrative entities like cities or streets. We need users to select accurate addresses.
- address instructs the Place Autocomplete service to return only geocoding results with a precise address.
Gotcha! That is what we need, right?... Basically, yes. However, it does not allow users to search by postcode, which is a common case for us.
So to achieve precise search results by both street names and postcodes, we wrote a custom filter. Thanks to StackOverflow for the inspiration.
export const filterPredictions = ( results: Array<google.maps.places.AutocompletePrediction> ): Array<google.maps.places.AutocompletePrediction> => results.filter(({ types }) => { // Keep predictions that are street addresses or postal codes if (types.includes("street_address") || types.includes("postal_code")) { return true; } // For geocode types, check for building numbers (premise/subpremise) if (types.includes("geocode")) { return types.some((type) => ["premise", "subpremise"].includes(type)); } return false; // Filter out irrelevant types });
If the result includes the street_address or postal_code, we assume it as the correct result.
If it has the geocode type, we check for the premise or subpremise (shortly saying, the building number or name). More about types you can read here.
The result we achieved:
Step 4: Fetching Address Details with Geocoder
AutocompleteService returns only search predictions, but not the place details we need. However, with the place id and Geocoder we can get details like exact address, country, postal code and coordinates.
Geocoder was initially created to make conversions between addresses and coordinates, but it completely covers our needs.
If you need to have additional information about the place like reviews and comments, you can use the Places API.
Let's add a new method to our hook:
// Function to get detailed information about a place using its place id const getPlaceById = async ( placeId: string // The place_id from the AutocompleteService ): Promise<google.maps.GeocoderResult | null> => { const geocoder = new google.maps.Geocoder(); // Create a new instance of Geocoder try { const { results } = await geocoder.geocode({ placeId }); // Return the first result return results[0]; } catch { // In case of error, return null return null; } };
To unify the results between counties, where different administrative levels and entities exist, Google uses the address components structure. Let's check an example:
To format the address, we need the Baker Street 221B, NW1 6XE, London (street_number route, postal_code, locality). But, in some cases, the keys structure might differ. To cover it we made an unified serializer:
// Helper function to extract a specific address component by its type (e.g., street_address, postal_code) export const pickAddressComponentByType = ( result: google.maps.GeocoderResult, type: Array<string> ): string => result.address_components.find((component) => component.types.some((componentType) => type.includes(componentType)) )?.long_name || ""; // Function to serialize the geocoded result into a structured format export const serializeGeocoderResult = ( result: google.maps.GeocoderResult ): TFormatedGeocoderResult => ({ formattedAddress: result.formatted_address, streetAddress: pickAddressComponentByType(result, [ "street_address", "premise", "route", ]), streetNumber: pickAddressComponentByType(result, ["street_number"]), city: pickAddressComponentByType(result, [ "locality", "postal_town", "administrative_area_level_2", ]), country: pickAddressComponentByType(result, ["country"]), state: pickAddressComponentByType(result, ["administrative_area_level_1"]), postalCode: pickAddressComponentByType(result, ["postal_code"]), latitude: result.geometry.location.lat(), longitude: result.geometry.location.lng(), });
Notice, that we verified it only for Great Britain. So maybe you might need to enhance it for your specific cases.
Improvements for Google Maps Autocomplete
- Add the input debounce and minimum characters restriction to reduce the number of requests. Debouncing ensures that the API is only called after a certain delay, helping to reduce unnecessary requests as the user types. You can check these improvements in DEMO Sandbox.
- If you're open in your budget, you can fetch all of the places by their id and show users the options in the format you need, but not in the Google Autocomplete format.
Conclusions: Smart Address Search
In this article, I have shown how we can use different Google Maps API's to build address fields, that can replace full address forms and drastically reduce the time users need to spend on it, reducing the number of mistakes on the users' side.
Check out the DEMO sandbox, but don’t forget to set your own GOOGLE_MAPS_API_KEY.
Feel free to send your questions and suggestions in comments. I'll be glad for any conversations??.
The above is the detailed content of Creating a Smart Address Search with Google Maps API and React. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Both Python and JavaScript's choices in development environments are important. 1) Python's development environment includes PyCharm, JupyterNotebook and Anaconda, which are suitable for data science and rapid prototyping. 2) The development environment of JavaScript includes Node.js, VSCode and Webpack, which are suitable for front-end and back-end development. Choosing the right tools according to project needs can improve development efficiency and project success rate.

C and C play a vital role in the JavaScript engine, mainly used to implement interpreters and JIT compilers. 1) C is used to parse JavaScript source code and generate an abstract syntax tree. 2) C is responsible for generating and executing bytecode. 3) C implements the JIT compiler, optimizes and compiles hot-spot code at runtime, and significantly improves the execution efficiency of JavaScript.

JavaScript is widely used in websites, mobile applications, desktop applications and server-side programming. 1) In website development, JavaScript operates DOM together with HTML and CSS to achieve dynamic effects and supports frameworks such as jQuery and React. 2) Through ReactNative and Ionic, JavaScript is used to develop cross-platform mobile applications. 3) The Electron framework enables JavaScript to build desktop applications. 4) Node.js allows JavaScript to run on the server side and supports high concurrent requests.

Python is more suitable for data science and automation, while JavaScript is more suitable for front-end and full-stack development. 1. Python performs well in data science and machine learning, using libraries such as NumPy and Pandas for data processing and modeling. 2. Python is concise and efficient in automation and scripting. 3. JavaScript is indispensable in front-end development and is used to build dynamic web pages and single-page applications. 4. JavaScript plays a role in back-end development through Node.js and supports full-stack development.
