Some time ago, Google began showing a warning that AutocompleteService
would no longer be available for new users, and recommended migrating to AutocompleteSuggestion
instead.
In this article, I’ll walk you through the changes required to migrate the previous solution to the new API.
Step 1: Update Dependencies
First, make sure you update your @react-google-maps/api
package 🙂.
You’ll also need to enable Places API (New) in the Google Maps Console.
Step 2: Define a New Search Method
The API is fairly similar, so you’ll find minimal changes necessary:
const searchPlacesV2 = async (
query: string,
options?: Omit<google.maps.places.AutocompleteRequest, 'input'>,
): Promise<Array<google.maps.places.AutocompleteSuggestion>> => {
// Load AutocompleteSuggestion from Google Maps API
const { AutocompleteSuggestion } = (await google.maps.importLibrary('places')) as google.maps.PlacesLibrary;
try {
// Fetch place predictions based on user query
const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions({
...options,
input: query,
});
// Return the list of predictions to display to the user
return suggestions;
} catch (error) {
// If there's an error, return an empty array
console.error('Failed to search places', error);
return [];
}
};
Step 3: Refine AutocompleteSuggestion
Results
The componentRestrictions.country
field has been replaced with includedRegionCodes
. The limit on region codes has also been increased to 15!
You can find the list of codes here.
const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions({
...options,
input: query,
includedRegionCodes: ['gb', 'us'],
});
Step 4: Additional Filtering of Suggestions
The new API returns an array of AutocompleteSuggestion
objects, which have a slightly different structure.
export const serializePlacesSearchV2ToOptions = (
results: Array<google.maps.places.AutocompleteSuggestion>,
): Array<{
label: string;
value: string;
}> =>
results
// Map to PlacePrediction object
.map(place => place.placePrediction)
// Filtering by type remains the same
.filter(({ types }) => {
if (types.includes('street_address') || types.includes('postal_code')) return true;
if (types.includes('geocode')) {
return types.some(type => ['premise', 'subpremise'].includes(type));
}
return false;
})
.map(place => ({
label: [place.mainText.text, place.secondaryText.text].join(', '),
value: place.placeId,
}));
Note: the new API no longer includes a description
field for the full address, but you can compose it using mainText.text
and secondaryText.text
.
Extra: Filtering by Country and a Specific State
In our use case, we needed to restrict results to Great Britain and Texas.
Google Maps now supports locationRestriction
, which allows setting bounding boxes. However, it supports only one region at a time. Since GB and Texas are far apart, we used a basic workaround:
.filter(({ label }) => {
// If search is set to GB only, do nothing
if (!regionCodes?.includes('us')) return true;
// Split the address by comma and look for "UK" or "TX" otherwise
return ['UK', 'TX'].some(regionCode =>
label?.split(', ').pop().trim()?.toUpperCase().includes(regionCode),
);
});
In practice, the last part of secondaryText.text
from Google Maps typically includes the state or country code, which makes this simple filter effective for our use case.
Feel free to share your questions or suggestions in the comments — I’d love to continue the conversation 🌊🙌
Top comments (0)