Heim >Web-Frontend >js-Tutorial >Erstellen einer intelligenten Adresssuche mit Google Maps API und React

Erstellen einer intelligenten Adresssuche mit Google Maps API und React

Patricia Arquette
Patricia ArquetteOriginal
2024-10-07 22:17:02818Durchsuche

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).

Creating a Smart Address Search with Google Maps API and React

Schritt 1: Google Maps API-Einrichtung in React

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,
  };
};


Schritt 2: Ortssuche mit Google Autocomplete

Der Places Autocomplete Service bietet eine API für die Suche innerhalb der Orte. Es bietet zwei Methoden:

  • getQueryPredictions() gibt Ergebnisse zurück, die nicht unbedingt die „place_id“ haben müssen. Es können auch Suchbegriffe oder Ortsgruppen wie Restaurants enthalten sein.
  • getPlacePredictions() gibt genaue Orte und Verwaltungseinheiten zurück.

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>
  );
}


Creating a Smart Address Search with Google Maps API and React

Aufgrund der Vorhersagen interessieren uns die 3 Felder:

  1. Geben Sie den vollständigen Namen ein.
  2. Orts-ID.
  3. Ortstypen – das Array von Typen, zu denen die Entität gehört. Eine vollständige Typenliste finden Sie hier. Wir nutzen sie für die zusätzliche Ergebnisfilterung.

Schritt 3: Verfeinern der Ergebnisse der automatischen Vervollständigung

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"],
    });


  • Geokodierungstyp weist den Place Autocomplete-Dienst an, nur Geokodierungsergebnisse und keine Geschäftsergebnisse zurückzugeben.

Dazu gehören aber auch die größeren Verwaltungseinheiten wie Städte oder Straßen. Wir brauchen Benutzer, die genaue Adressen auswählen.

  • Adresse weist den Place Autocomplete-Dienst an, nur Geokodierungsergebnisse mit einer genauen Adresse zurückzugeben.

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:

Creating a Smart Address Search with Google Maps API and React

Schritt 4: Adressdetails mit Geocoder abrufen

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:

Creating a Smart Address Search with Google Maps API and React
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

  1. 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.
  2. 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??.

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn