Using Google Place to build a country autocomplete
Tags: country, autocomplete, google
Published: 2023-12-08 01:43:52

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 see 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](https://country-autocomplete.vercel.app).


## Prerequisites

- [Google Places API Key](https://developers.google.com/maps/documentation/places/web-service/get-api-key)
- [React Select dependency](https://react-select.com/home)

## Getting Started

We will begin with our class 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.

```tsx
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.

```tsx
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.

```jsx
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

Now we are ready to implement the country autocomplete component using React Select library and the Google Helper class we just created.

```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 us to load the options asynchronously, so we can use the `loadOptions` prop to call our `searchCountry` function and get all the countries.

We are also defining the `handleCountrySelection` function that will be 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](https://github.com/a-maggi/country-autocomplete), 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\_](https://twitter.com/amaggi_) or leave a question on this post.