>웹 프론트엔드 >JS 튜토리얼 >Google Maps API 및 React를 사용하여 스마트 주소 검색 만들기

Google Maps API 및 React를 사용하여 스마트 주소 검색 만들기

Patricia Arquette
Patricia Arquette원래의
2024-10-07 22:17:02818검색

Google fournit un accès robuste à son API Maps, qui peut être exploitée pour diverses fonctionnalités basées sur la localisation et tâches liées aux cartes. Dans cet article, j'expliquerai comment nous avons utilisé l'API Google AutocompleteService pour créer un champ de recherche d'adresse intelligente qui remplace un formulaire d'adresse complète.

En utilisant cette approche, nous avons réduit les erreurs de saisie des utilisateurs et amélioré l'expérience utilisateur en simplifiant le processus de saisie d'adresse, le rendant plus rapide et plus précis (1 saisie intelligente contre 3, hein).

Creating a Smart Address Search with Google Maps API and React

Étape 1 : configuration de l'API Google Maps dans React

Tout d'abord, pour travailler avec l'API Maps, vous devrez l'activer dans Google Maps Platform et obtenir la clé API.

Dans notre projet, nous utilisons le package @react-google-maps/api (npm i @react-google-maps/api).

Initialisons le SDK avec le hook useGoogleMapsApi personnalisé, pour le rendre réutilisable au sein de l'application :


const useGoogleMapsApi = () => {
  const api = useJsApiLoader({
    id: "app",
    googleMapsApiKey: "", // set your Public key
  });

  return {
    ...api,
  };
};


Étape 2 : Effectuer une recherche avec la saisie semi-automatique de Google

Le service Places Autocomplete fournit une API pour effectuer une recherche dans les lieux. Il propose 2 méthodes :

  • getQueryPredictions() renvoie des résultats qui n'ont pas nécessairement le "place_id". Il peut également inclure des termes de recherche ou des groupes de lieux comme des restaurants.
  • getPlacePredictions() renvoie des lieux et entités administratives précis.

Pour implémenter notre recherche, nous avons utilisé la méthode getPlacePredictions(). Ajoutons cette méthode à notre code et renvoyons-la depuis le hook.


// 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 [];
  }
};


L'interface AutocompletionRequest utilise le champ de saisie comme requête de recherche et d'autres options, ce qui permet de rendre une recherche plus précise. Nous en reparlerons plus tard.
Nous utiliserons une simple saisie et une liste de résultats pour notre démo.


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

D'après les prédictions, nous nous intéressons aux 3 domaines :

  1. Nom complet du lieu.
  2. Identifiant du lieu.
  3. Types de lieux - le tableau de types auquel l'entité appartient. Vous pouvez trouver une liste complète des types ici. Nous les utilisons pour le filtrage supplémentaire des résultats.

Étape 3 : Affiner les résultats de la saisie semi-automatique

L'interface AutocompleteService comporte de nombreuses entrées qui permettent de rendre une recherche plus précise.

Le composant de champRestrictions nous permet de restreindre les résultats de recherche à un pays spécifique. Il prend en charge jusqu'à 5 pays et nécessite que les codes de pays soient conformes à la norme ISO 3166-1 Alpha-2. Ici vous pouvez trouver une liste des codes des pays.


    const { predictions } = await autocomplete.getPlacePredictions({
      ...options,
      input: query,
      componentRestrictions: {
        country: ["gb"],
      },
    });


Pour que notre champ ne prête pas à confusion pour les utilisateurs, nous devons exclure des endroits comme les parcs, les aéroports, etc. des résultats de recherche. Le service Autocomplete dispose d'un champ types pour spécifier les types de prédictions à renvoyer. Mais un seul type est autorisé pour l'AutocompleteService.


    const { predictions } = await autocomplete.getPlacePredictions({
      ...options,
      input: query,
      componentRestrictions: {
        country: ["gb"],
      },
      types: ["geocode"],
    });


  • Le type de géocode demande au service Place Autocomplete de renvoyer uniquement les résultats de géocodage, plutôt que les résultats commerciaux.

Mais cela inclut également les plus grandes entités administratives comme les villes ou les rues. Nous avons besoin que les utilisateurs sélectionnent des adresses précises.

  • adresse demande au service Place Autocomplete de renvoyer uniquement les résultats de géocodage avec une adresse précise.

Je t'ai eu ! C'est ce dont nous avons besoin, n'est-ce pas ?... Au fond, oui. Cependant, il ne permet pas aux utilisateurs d'effectuer une recherche par code postal, ce qui est un cas courant chez nous.

Ainsi, pour obtenir des résultats de recherche précis par nom de rue et par code postal, nous avons écrit un filtre personnalisé. Merci à StackOverflow pour l'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
  });


Si le résultat inclut l'adresse_rue ou le code_postal, nous le considérons comme le résultat correct.
S'il est de type géocode, nous vérifions le local ou le sous-local (en bref, le numéro ou le nom du bâtiment). Pour en savoir plus sur les types, vous pouvez lire ici.

Le résultat que nous avons obtenu :

Creating a Smart Address Search with Google Maps API and React

Étape 4 : Récupération des détails de l'adresse avec Geocoder

AutocompleteService renvoie uniquement les prédictions de recherche, mais pas les détails du lieu dont nous avons besoin. Cependant, avec l'identifiant du lieu et le géocodeur, nous pouvons obtenir des détails tels que l'adresse exacte, le pays, le code postal et les coordonnées.
Geocoder a été initialement créé pour faire des conversions entre adresses et coordonnées, mais il couvre complètement nos besoins.
Si vous avez besoin d'informations supplémentaires sur le lieu, comme des avis et des commentaires, vous pouvez utiliser l'API Places.

Ajoutons une nouvelle méthode à notre hook :


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


Pour unifier les résultats entre les comtés, où existent différents niveaux administratifs et entités, Google utilise la structure des composants d'adresse. Vérifions un exemple :

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

위 내용은 Google Maps API 및 React를 사용하여 스마트 주소 검색 만들기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.