Using Google Place to build a Country Autocomplete

December 07, 2023

4 min read999 views

Using Google Place to build a Country Autocomplete

Google Places API is a service that provides information about places and addresses. This functionality is very useful for applications requiring specific location input from users.

One missing feature in the Google Places API is the ability to search for countries. In this tutorial, we will explore how to implement a country autocomplete feature using the Google Places API and the React Select library.

You can see the final result at country-autocomplete.vercel.app.

Prerequisites

Getting Started

We will start with a class function that will handle the Google Places API. This class will have all the methods that we will need to interface with the API and ultimately generate the countries list for our autocomplete dropdown.

The first method is the SearchCountry. This will receive a search string and return a list of countries matching that value. We are using the AutocompleteService from the Google Places API to get the list of matches. We limit results to 'regions' to exclude streets or cities.

SearchCountry(search: string): Promise<google.maps.places.AutocompletePrediction[] | null> {
	new Promise<google.maps.places.AutocompletePrediction[] | null>((resolve) => {
		this.autocompleteService?.getPlacePredictions({ input: search, types: ["(regions)"] }, (predictions) => {
			if (!predictions) {
			  resolve(null);
			} else {
				resolve(predictions.filter((prediction) => prediction.types.includes("country")) || null);
			}
		});
	});
}

The searchPlace method utilizes the Geocoding service to retrieve additional information for a provided place ID obtained from the AutocompleteService response.

searchPlace(search: string): Promise<google.maps.GeocoderResult | null> {
  return new Promise((resolve) => {
    this.geocoder.geocode({ placeId: search }, (results, status) => {
      if (status === "OK" && results && results[0]) {
        resolve(results[0]);
      } else {
        resolve(null);
      }
    });
  });
}

Finally, we will use the getCountry method to parse the geocoder result and obtain the country code.

getCountryCode(place: google.maps.places.PlaceResult): string | false {
  const addressComponents = place.address_components || [];
  for (const component of addressComponents) {
    if (component.types.includes("country")) {
      return component.short_name || false;
    }
    if (component.types.length === 2 && component.types.includes("political")) {
      return component.short_name || false;
    }
  }
  return false;
}

Writing the Autocomplete component

We're now prepared to implement the country autocomplete component using React Select library and the Google Helper class we've just created.

CountryAutocomplete.tsx
import GoogleHelper from "./GoogleHelper";
import AsyncSelect from "react-select/async";
import CountryAutocompleteProps from "./types";

const Google = new GoogleHelper('myKey');

export function CountryAutocomplete(props: CountryAutocompleteProps) {
  const handleCountrySelection = async (country: Option | null) => {
		if (!country) return;
    const place = await Google.searchPlace(country.value as string);
    if (!place) return;
    const countryCode = Google.getCountry(place);
    props.onSelect({ value: countryCode, label: country.label });
	};
	const handleSearchCountries = (inputValue: string) => {
		return new Promise<OptionShape[]>((resolve) => {
			Google
				.searchCountry(inputValue)
				.then((results) => {
					return resolve(formatAutocompleteResult(results));
				})
				.catch((err) => {
					return resolve([]);
				});
		});
  }
  return (
    <AsyncSelect
      value={props.value}
      noOptionsMessage={(i) => (!i.inputValue ? "Type to search for a country" : "No results found")}
      placeholder="Type to search for a country"
      loadOptions={handleSearchCountries}
      onChange={handleCountrySelection}
      cacheOptions={true}
      defaultOptions={true}
    />
  )
}

We can see that we are using the AsyncSelect component from React Select. This component allows to load the options asynchronously, so we can use the loadOptions prop to call our searchCountry function and get all the countries.

Additionally, we've defined the handleCountrySelection function, which is called when the user selects a country from the dropdown. This function will call the searchPlace function to get the extra information for the selected country, and then call the onSelect prop to notify the parent component that a country was selected.

Wrapping up

If you want to see the full code, you can visit this GitHub repository, where you will find this same example packed as an npm library to be easily consumed in your projects.

I hope this tutorial has been helpful and helped you to understand a bit better how to use the Google Places API.

If you have any questions or comments, feel free to reach me at @amaggi_.