Maison > interface Web > js tutoriel > Création d'une recherche d'adresse intelligente avec l'API Google Maps et React

Création d'une recherche d'adresse intelligente avec l'API Google Maps et React

Patricia Arquette
Libérer: 2024-10-07 22:17:02
original
801 Les gens l'ont consulté

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


Copier après la connexion

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


Copier après la connexion

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


Copier après la connexion

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


Copier après la connexion

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


Copier après la connexion
  • 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
  });


Copier après la connexion

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


Copier après la connexion

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


Copier après la connexion

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal