Heim >Web-Frontend >js-Tutorial >Erstellen einer intelligenten Adresssuche mit Google Maps API und React
Google bietet robusten Zugriff auf seine Maps-API, die für verschiedene standortbasierte Funktionen und kartenbezogene Aufgaben genutzt werden kann. In diesem Artikel erkläre ich, wie wir die Google AutocompleteService API genutzt haben, um ein intelligentes Adresssuchfeld zu erstellen, das ein vollständiges Adressformular ersetzt.
Durch die Verwendung dieses Ansatzes haben wir Benutzereingabefehler reduziert und das Benutzererlebnis verbessert, indem wir den Adresseingabeprozess vereinfacht und ihn schneller und genauer gemacht haben (1 intelligente Eingabe vs. 3, nicht wahr).
Um mit der Maps-API arbeiten zu können, müssen Sie diese zunächst in Google Maps Platform aktivieren und den API-Schlüssel erhalten.
In unserem Projekt verwenden wir das @react-google-maps/api-Paket (npm i @react-google-maps/api).
Lassen Sie uns das SDK mit dem benutzerdefinierten useGoogleMapsApi-Hook initialisieren, um es innerhalb der Anwendung wiederverwendbar zu machen:
const useGoogleMapsApi = () => { const api = useJsApiLoader({ id: "app", googleMapsApiKey: "", // set your Public key }); return { ...api, }; };
Der Places Autocomplete Service bietet eine API für die Suche innerhalb der Orte. Es bietet zwei Methoden:
Um unsere Suche zu implementieren, haben wir die Methode getPlacePredictions() verwendet. Fügen wir diese Methode zu unserem Code hinzu und geben sie vom Hook zurück.
// 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 []; } };
Die AutocompletionRequest-Schnittstelle verwendet das Eingabefeld als Suchabfrage und andere Optionen, was eine genauere Suche ermöglicht. Wir werden später darüber sprechen.
Für unsere Demo verwenden wir eine einfache Eingabe und eine Ergebnisliste.
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> ); }
Aufgrund der Vorhersagen interessieren uns die 3 Felder:
Die AutocompleteService-Schnittstelle verfügt über eine Reihe von Eingaben, die eine genauere Suche ermöglichen.
Mit der Feldkomponente „Restrictions“ können wir die Suchergebnisse auf ein bestimmtes Land eingrenzen. Es unterstützt bis zu 5 Länder und erfordert, dass die Ländercodes dem ISO 3166-1 Alpha-2-Standard entsprechen. Hier finden Sie eine Liste der Ländercodes.
const { predictions } = await autocomplete.getPlacePredictions({ ...options, input: query, componentRestrictions: { country: ["gb"], }, });
Damit unser Feld für die Benutzer nicht verwirrend ist, müssen wir Orte wie Parks, Flughäfen usw. aus den Suchergebnissen ausschließen. Der Autocomplete-Dienst verfügt über Feldtypen zur Angabe der zurückzugebenden Vorhersagetypen. Aber nur ein Typ ist für den AutocompleteService zulässig.
const { predictions } = await autocomplete.getPlacePredictions({ ...options, input: query, componentRestrictions: { country: ["gb"], }, types: ["geocode"], });
Dazu gehören aber auch die größeren Verwaltungseinheiten wie Städte oder Straßen. Wir brauchen Benutzer, die genaue Adressen auswählen.
Verstanden! Das ist es, was wir brauchen, oder? ... Im Grunde ja. Es ist jedoch nicht möglich, dass Benutzer nach Postleitzahlen suchen, was bei uns häufig der Fall ist.
Um präzise Suchergebnisse sowohl nach Straßennamen als auch nach Postleitzahlen zu erhalten, haben wir einen benutzerdefinierten Filter geschrieben. Vielen Dank an StackOverflow für die 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 });
Wenn das Ergebnis die Straßenadresse oder Postleitzahl enthält, gehen wir davon aus, dass es sich um das korrekte Ergebnis handelt.
Wenn es den Geocode-Typ hat, prüfen wir das Gebäude oder das Gebäude (kurz gesagt, die Gebäudenummer oder den Namen). Mehr über Typen können Sie hier lesen.
Das Ergebnis, das wir erzielt haben:
AutocompleteService gibt nur Suchvorhersagen zurück, nicht jedoch die Ortsdetails, die wir benötigen. Mit der Orts-ID und dem Geocoder können wir jedoch Details wie genaue Adresse, Land, Postleitzahl und Koordinaten abrufen.
Geocoder wurde ursprünglich entwickelt, um Konvertierungen zwischen Adressen und Koordinaten durchzuführen, deckt jedoch vollständig unsere Anforderungen ab.
Wenn Sie zusätzliche Informationen über den Ort wie Bewertungen und Kommentare benötigen, können Sie die Places-API verwenden.
Fügen wir unserem Hook eine neue Methode hinzu:
// 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; } };
Um die Ergebnisse zwischen Landkreisen zu vereinheitlichen, in denen unterschiedliche Verwaltungsebenen und Einheiten existieren, verwendet Google die Adresskomponentenstruktur. Schauen wir uns ein Beispiel an:
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.
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??.
Das obige ist der detaillierte Inhalt vonErstellen einer intelligenten Adresssuche mit Google Maps API und React. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!