✨ Introducing use-places-autocomplete: React hook for Google Maps Places Autocomplete
Tags: react, hook, opensource, javascript
Published: 2020-02-11 14:01:19

Yooo guys! with [use-places-autocomplete](https://github.com/wellyshen/use-places-autocomplete) you can build your own places autocomplete UI like the following demo in 10 minutes, no kidding 😉

![demo](https://user-images.githubusercontent.com/21308003/91069764-6133e680-e668-11ea-8a57-bfbea2cfbd29.gif)

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

## Features

- 🧠 Provides intelligent places suggestions powered by [Google Maps Places API](https://developers.google.com/maps/documentation/javascript/places).
- 🎣 Builds your own customized autocomplete UI by React [hook](https://reactjs.org/docs/hooks-custom.html#using-a-custom-hook).
- 🔧 [Utility functions](https://github.com/wellyshen/use-places-autocomplete#utility-functions) to do geocoding and get geographic coordinates using [Google Maps Geocoding API](https://developers.google.com/maps/documentation/javascript/geocoding).
- 🤑 Built-in [cache mechanism](https://github.com/wellyshen/use-places-autocomplete#cache-data-for-you) for you to save the cost of Google APIs.
- 💰 Built-in debounce mechanism for you to lower the cost of Google APIs.
- 🚀 Supports asynchronous Google script loading.
- 📜 Supports [TypeScript](https://www.typescriptlang.org) type definition.
- ⌨️ Builds a UX-rich component (e.g. [WAI-ARIA compliant](https://rawgit.com/w3c/aria-practices/master/aria-practices-DeletedSectionsArchive.html#autocomplete) and keyword support) via comprehensive [demo code](https://github.com/wellyshen/use-places-autocomplete/blob/master/src/App/index.tsx).
- 🦔 Tiny size ([~ 1.7KB gzipped](https://bundlephobia.com/result?p=use-places-autocomplete)). No external dependencies, aside for the `react`.

## How does it work?

First, use the `script` tag to load the library in your project.

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

Start to build our component. Check the [API](https://github.com/wellyshen/use-places-autocomplete#api) out to learn more.

```js
import usePlacesAutocomplete, {
  getGeocode,
  getLatLng,
} from "use-places-autocomplete";
import useOnclickOutside from "react-cool-onclickoutside";

const PlacesAutocomplete = () => {
  const {
    ready,
    value,
    suggestions: { status, data },
    setValue,
    clearSuggestions,
  } = usePlacesAutocomplete({
    requestOptions: {
      /* Define search scope here */
    },
    debounce: 300,
  });
  const ref = useOnclickOutside(() => {
    // When user clicks outside of the component, we can dismiss
    // the searched suggestions by calling this method
    clearSuggestions();
  });

  const handleInput = (e) => {
    // Update the keyword of the input element
    setValue(e.target.value);
  };

  const handleSelect =
    ({ description }) =>
    () => {
      // When 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 functions
      getGeocode({ address: description }).then((results) => {
        const { lat, lng } = getLatLng(results[0]);
        console.log("📍 Coordinates: ", { lat, lng });
      });
    };

  const renderSuggestions = () =>
    data.map((suggestion) => {
      const {
        place_id,
        structured_formatting: { main_text, secondary_text },
      } = suggestion;

      return (
        <li key={place_id} onClick={handleSelect(suggestion)}>
          <strong>{main_text}</strong> <small>{secondary_text}</small>
        </li>
      );
    });

  return (
    <div ref={ref}>
      <input
        value={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>
  );
};
```

Easy right? This is the magic of the `usePlacesAutocomplete` ✨. I just show you how does it work via the minimal example. However there're more things you can do for a UX rich autocomplete component, like [WAI-ARIA compliant](https://rawgit.com/w3c/aria-practices/master/aria-practices-DeletedSectionsArchive.html#autocomplete) and keyword support as my [demo](https://use-places-autocomplete.netlify.com) (check the [code](https://github.com/wellyshen/use-places-autocomplete/blob/master/src/App/index.tsx)), a keyword clear button, search history etc.

> 💡 [react-cool-onclickoutside](https://github.com/wellyshen/react-cool-onclickoutside) is my other hook library, which can help you handle the interaction of user clicks outside of the component(s).

---

Thanks for reading, for more usage details checkout the project's GitHub page: https://github.com/wellyshen/use-places-autocomplete

You can also install this package is distributed via [npm](https://www.npmjs.com/package/use-places-autocomplete).

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

When working with TypeScript you need to install the [@types/googlemaps](https://www.npmjs.com/package/@types/googlemaps) as a `devDependencies`.

```sh
$ yarn add --dev @types/googlemaps
# or
$ npm install --save-dev @types/googlemaps
```