Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

😎 📍 React hook for Google Maps Places Autocomplete.

License

NotificationsYou must be signed in to change notification settings

wellyshen/use-places-autocomplete

👀 We're actively seeking dedicated maintainers for the repo — if you're interested, please contact me directly.

This is a Reacthook forGoogle Maps Places Autocomplete, which helps you build a UI component with the feature of place autocomplete easily! By leveraging the power ofGoogle Maps Places API, you can provide a great UX (user experience) for user interacts with your search bar or form, etc. Hope you guys 👍🏻 it.

❤️ it? ⭐️ it onGitHub orTweet about it.

build statuscoverage statusnpm versionnpm downloadsnpm downloadsgzip sizeAll ContributorsPRs welcomeTwitter URL

Live Demo

demo

⚡️ Try yourself:https://use-places-autocomplete.netlify.app

Features

Requirement

To useuse-places-autocomplete, you must usereact@16.8.0 or greater which includes hooks.

Installation

This package is distributed vianpm.

$ yarn add use-places-autocomplete# or$ npm install --save use-places-autocomplete

When working with TypeScript you need to install the@types/google.maps as adevDependencies.

$ yarn add --dev @types/google.maps# or$ npm install --save-dev @types/google.maps

Getting Started

usePlacesAutocomplete is based on thePlaces Autocomplete (or more specificdocs) ofGoogle Maps Place API. If you are unfamiliar with these APIs, we recommend you review them before we start.

Setup APIs

To use this hook, there're two things we need to do:

  1. Enable Google Maps Places API.
  2. Get an API key.

Load the library

Use thescript tag to load the library in your project and pass the value of thecallback parameter to thecallbackName option.

<scriptdefersrc="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=YOUR_CALLBACK_NAME"></script>

⚠️ If you got a global function not found error. Make sureusePlaceAutocomplete is declared before the script was loaded. You can use theasync or defer attribute of the<script> element to achieve that.

Create the component

Now we can start to build our component. Check theAPI out to learn more.

importusePlacesAutocomplete,{getGeocode,getLatLng,}from"use-places-autocomplete";importuseOnclickOutsidefrom"react-cool-onclickoutside";constPlacesAutocomplete=()=>{const{    ready,    value,suggestions:{ status, data},    setValue,    clearSuggestions,}=usePlacesAutocomplete({callbackName:"YOUR_CALLBACK_NAME",requestOptions:{/* Define search scope here */},debounce:300,});constref=useOnclickOutside(()=>{// When the user clicks outside of the component, we can dismiss// the searched suggestions by calling this methodclearSuggestions();});consthandleInput=(e)=>{// Update the keyword of the input elementsetValue(e.target.value);};consthandleSelect=({ description})=>()=>{// When the user selects a place, we can replace the keyword without request data from API// by setting the second parameter to "false"setValue(description,false);clearSuggestions();// Get latitude and longitude via utility functionsgetGeocode({address:description}).then((results)=>{const{ lat, lng}=getLatLng(results[0]);console.log("📍 Coordinates: ",{ lat, lng});});};constrenderSuggestions=()=>data.map((suggestion)=>{const{        place_id,structured_formatting:{ main_text, secondary_text},}=suggestion;return(<likey={place_id}onClick={handleSelect(suggestion)}><strong>{main_text}</strong><small>{secondary_text}</small></li>);});return(<divref={ref}><inputvalue={value}onChange={handleInput}disabled={!ready}placeholder="Where are you going?"/>{/* We can use the "status" to decide whether we should display the dropdown or not */}{status==="OK"&&<ul>{renderSuggestions()}</ul>}</div>);};

💡react-cool-onclickoutside is my other hook library, which can help you handle the interaction of user clicks outside of the component(s).

Easy right? This is the magic ofusePlacesAutocomplete ✨. I just showed you how it works via a minimal example. However, you can build a UX rich autocomplete component, likeWAI-ARIA compliant and keyword interaction like mydemo, by checking thecode or integrating this hook with thecombobox ofReach UI to achieve that.

Edit usePlacesAutocomplete x Reach UI

importusePlacesAutocompletefrom"use-places-autocomplete";import{Combobox,ComboboxInput,ComboboxPopover,ComboboxList,ComboboxOption,}from"@reach/combobox";import"@reach/combobox/styles.css";constPlacesAutocomplete=()=>{const{    ready,    value,suggestions:{ status, data},    setValue,}=usePlacesAutocomplete({callbackName:"YOUR_CALLBACK_NAME"});consthandleInput=(e)=>{setValue(e.target.value);};consthandleSelect=(val)=>{setValue(val,false);};return(<ComboboxonSelect={handleSelect}aria-labelledby="demo"><ComboboxInputvalue={value}onChange={handleInput}disabled={!ready}/><ComboboxPopover><ComboboxList>{status==="OK"&&data.map(({ place_id, description})=>(<ComboboxOptionkey={place_id}value={description}/>))}</ComboboxList></ComboboxPopover></Combobox>);};

Lazily Initializing The Hook

When loading the Google Maps Places API via a 3rd-party library, you may need to wait for the script to be ready before using this hook. However, you can lazily initialize the hook in the following ways, depending on your use case.

Option 1, manually initialize the hook:

importusePlacesAutocompletefrom"use-places-autocomplete";constApp=()=>{const{ init}=usePlacesAutocomplete({initOnMount:false,// Disable initializing when the component mounts, default is true});const[loading]=useGoogleMapsApi({library:"places",onLoad:()=>init(),// Lazily initializing the hook when the script is ready});return<div>{/* Some components... */}</div>;};

Option 2, wrap the hook into a conditional component:

importusePlacesAutocompletefrom"use-places-autocomplete";constPlacesAutocomplete=()=>{const{ ready, value, suggestions, setValue}=usePlacesAutocomplete();return<div>{/* Some components... */}</div>;};constApp=()=>{const[loading]=useGoogleMapsApi({library:"places"});return(<div>{!loading ?<PlacesAutocomplete/> :null}{/* Other components... */}</div>);};

Cache Data For You

By default, this library caches the response data to help you save thecost of Google Maps Places API and optimize search performance.

constmethods=usePlacesAutocomplete({// Provide the cache time in seconds, the default is 24 hourscache:24*60*60,});

By the way, the cached data is stored via theWindow.sessionStorage API.

Custom cache key

You may need to have multiple caches. For example, if you use differentplace type restrictions for different pickers in your app.

constmethods=usePlacesAutocomplete({// Provide a custom cache keycacheKey:"region-restricted",});

Note that usePlacesAutocomplete will prefix this withupa-, so the above would becomeupa-region-restricted in sessionStorage.

API

constreturnObj=usePlacesAutocomplete(parameterObj);

Parameter object (optional)

When usingusePlacesAutocomplete, you can configure the following options via the parameter.

KeyTypeDefaultDescription
requestOptionsobjectTherequest options of Google Maps Places API except forinput (e.g. bounds, radius, etc.).
googleMapsobjectwindow.google.mapsIn case you want to provide your own Google Maps object, pass thegoogle.maps to it.
callbackNamestringThe value of thecallback parameter whenloading the Google Maps JavaScript library.
debouncenumber200Number of milliseconds to delay before making a request to Google Maps Places API.
cachenumber | false86400 (24 hours)Number of seconds tocache the response data of Google Maps Places API.
cacheKeystring"upa"Optional cache key so one can use multiple caches if needed.
defaultValuestring""Default value for theinput element.
initOnMountbooleantrueInitialize the hook with Google Maps Places API when the component mounts.

Return object

It's returned with the following properties.

KeyTypeDefaultDescription
readybooleanfalseThe ready status ofusePlacesAutocomplete.
valuestring""value for the input element.
suggestionsobject{ loading: false, status: "", data: [] }Seesuggestions.
setValuefunction(value, shouldFetchData = true) => {}SeesetValue.
clearSuggestionsfunctionSeeclearSuggestions.
clearCachefunction(key = cacheKey) => {}Clears thecached data.
initfunctionUseful whenlazily initializing the hook.

suggestions

The search result of Google Maps Places API, which contains the following properties:

  • loading: boolean - indicates the status of a request is pending or has been completed. It's useful for displaying a loading indicator for the user.
  • status: string - indicates the status of the API response, which has thesevalues. It's useful to decide whether we should display the dropdown or not.
  • data: array - an array of suggestion objects each contains all thedata.

setValue

Set thevalue of the input element. Use the case below.

importusePlacesAutocompletefrom"use-places-autocomplete";constPlacesAutocomplete=()=>{const{ value, setValue}=usePlacesAutocomplete();consthandleInput=(e)=>{// Place a "string" to update the value of the input elementsetValue(e.target.value);};return(<div><inputvalue={value}onChange={handleInput}/>{/* Render dropdown */}</div>);};

In addition, thesetValue method has an extra parameter, which can be used to disable hitting Google Maps Places API.

importusePlacesAutocompletefrom"use-places-autocomplete";constPlacesAutocomplete=()=>{const{    value,suggestions:{ status, data},    setValue,}=usePlacesAutocomplete();consthandleSelect=({ description})=>()=>{// When the user selects a place, we can replace the keyword without requesting data from the API// by setting the second parameter to "false"setValue(description,false);};constrenderSuggestions=()=>data.map((suggestion)=>(<likey={suggestion.place_id}onClick={handleSelect(suggestion)}>{/* Render suggestion text */}</li>));return(<div><inputvalue={value}onChange={handleInput}/>{status==="OK"&&<ul>{renderSuggestions()}</ul>}</div>);};

clearSuggestions

Calling the method will clear and reset all the properties of thesuggestions object to default. It's useful for dismissing the dropdown.

importusePlacesAutocompletefrom"use-places-autocomplete";importuseOnclickOutsidefrom"react-cool-onclickoutside";constPlacesAutocomplete=()=>{const{    value,suggestions:{ status, data},    setValue,    clearSuggestions,}=usePlacesAutocomplete();constref=useOnclickOutside(()=>{// When the user clicks outside of the component, call it to clear and reset the suggestions dataclearSuggestions();});constrenderSuggestions=()=>data.map((suggestion)=>(<likey={suggestion.place_id}onClick={handleSelect(suggestion)}>{/* Render suggestion text */}</li>));return(<divref={ref}><inputvalue={value}onChange={handleInput}/>{/* After calling the clearSuggestions(), the "status" is reset so the dropdown is hidden */}{status==="OK"&&<ul>{renderSuggestions()}</ul>}</div>);};

Utility Functions

We providegetGeocode,getLatLng,getZipCode, andgetDetails utils for you to do geocoding and get geographic coordinates when needed.

getGeocode

It helps you convert address (e.g. "Section 5, Xinyi Road, Xinyi District, Taipei City, Taiwan") into geographic coordinates (e.g. latitude 25.033976 and longitude 121.5645389), or restrict the results to a specific area byGoogle Maps Geocoding API.

In case you want to restrict the results to a specific area, you will have to pass theaddress and thecomponentRestrictions matching theGeocoderComponentRestrictions interface.

import{getGeocode}from"use-places-autocomplete";constparameter={address:"Section 5, Xinyi Road, Xinyi District, Taipei City, Taiwan",// orplaceId:"ChIJraeA2rarQjQRPBBjyR3RxKw",};getGeocode(parameter).then((results)=>{console.log("Geocoding results: ",results);}).catch((error)=>{console.log("Error: ",error);});

getGeocode is an asynchronous function with the following API:

  • parameter: object - you must supply one, only one ofaddress orlocation orplaceId and optionallybounds,componentRestrictions,region. It'll be passed asGeocoding Requests.
  • results: array - an array of objects each contains all thedata.
  • error: string - the error status of API response, which has thesevalues (except for "OK").

getLatLng

It helps you get thelat andlng from the result object ofgetGeocode.

import{getGeocode,getLatLng}from"use-places-autocomplete";constparameter={address:"Section 5, Xinyi Road, Xinyi District, Taipei City, Taiwan",};getGeocode(parameter).then((results)=>{const{ lat, lng}=getLatLng(results[0]);console.log("Coordinates: ",{ lat, lng});});

getLatLng is a function with the following API:

  • parameter: object - the result object ofgetGeocode.
  • latLng: object - contains the latitude and longitude properties.
  • error: any - an exception.

getZipCode

It helps you get thepostal_code from the result object ofgetGeocode.

import{getGeocode,getZipCode}from"use-places-autocomplete";constparameter={address:"Section 5, Xinyi Road, Xinyi District, Taipei City, Taiwan",};getGeocode(parameter)// By default we use the "long_name" value from API response, you can tell the utility to use "short_name"// by setting the second parameter to "true".then((results)=>{constzipCode=getZipCode(results[0],false);console.log("ZIP Code: ",zipCode);});

getZipCode is a function with the following API:

  • parameters - there're two parameters:
    • 1st: object - the result object ofgetGeocode.
    • 2nd: boolean - should use theshort_name or not fromAPI response, default isfalse.
  • zipCode: string | null - the zip code. If the address doesn't have a zip code it will benull.
  • error: any - an exception.

getDetails

Retrieves a great deal of information about a particular place ID (suggestion).

importusePlacesAutocomplete,{getDetails}from"use-places-autocomplete";constPlacesAutocomplete=()=>{const{ suggestions, value, setValue}=usePlacesAutocomplete();consthandleInput=(e)=>{// Place a "string" to update the value of the input elementsetValue(e.target.value);};constsubmit=()=>{constparameter={// Use the "place_id" of suggestion from the dropdown (object), here just taking the first suggestion for brevityplaceId:suggestions[0].place_id,// Specify the return data that you want (optional)fields:["name","rating"],};getDetails(parameter).then((details)=>{console.log("Details: ",details);}).catch((error)=>{console.log("Error: ",error);});};return(<div><inputvalue={value}onChange={handleInput}/>{/* Render dropdown */}<buttononClick={submit}>Submit Suggestion</button></div>);};

getDetails is an asynchronous function with the following API:

  • parameter: object -the request of the PlacesService'sgetDetails() method. You must supply theplaceId that you would like details about. If you do not specify any fields or omit the fields parameter you will get every field available.
  • placeResult: object | null -the details about the specific place your queried.
  • error: any - an exception.

⚠️ warning, you are billed based on how much information you retrieve, So it is advised that you retrieve just what you need.

Articles / Blog Posts

💡 If you have written any blog post or article aboutuse-places-autocomplete, please open a PR to add it here.

Contributors ✨

Thanks goes to these wonderful people (emoji key):

Welly
Welly

💻📖🚧
Kyle
Kyle

🌍
Lazar Karić
Lazar Karić

💻📖
Raif Harik
Raif Harik

💻📖🤔
Xerxes Jarquin
Xerxes Jarquin

🐛
Lucas O'Connell
Lucas O'Connell

📖
Keven Jesus
Keven Jesus

🐛
Vinicius Uehara
Vinicius Uehara

📖
Damon
Damon

💻
Matthew Marcus
Matthew Marcus

💻
Chris Sandvik
Chris Sandvik

💻
Thomas Yee
Thomas Yee

📖

This project follows theall-contributors specification. Contributions of any kind are welcome!

Sponsor this project

    Contributors14


    [8]ページ先頭

    ©2009-2025 Movatter.jp