Coder Social home page Coder Social logo

chawkios / use-places-autocomplete Goto Github PK

View Code? Open in Web Editor NEW

This project forked from wellyshen/use-places-autocomplete

0.0 1.0 0.0 6.83 MB

๐Ÿ˜Ž๐Ÿ“ React hook for Google Maps Places Autocomplete.

Home Page: https://use-places-autocomplete.netlify.com

License: MIT License

TypeScript 77.33% JavaScript 22.67%

use-places-autocomplete's Introduction

usePlacesAutocomplete

This is a React hook for Google Maps Places Autocomplete, which helps you build an UI component with the feature of place autocomplete easily! By leveraging the power of Google 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 on GitHub or Tweet about it.

build status coverage status npm version npm downloads npm downloads npm bundle size MIT licensed All Contributors PRs welcome Twitter URL

Live Demo

demo

โšก๏ธ Try yourself: https://use-places-autocomplete.netlify.com

Features

  • ๐Ÿง  Provide intelligent places suggestions powered by Google Maps Places API.
  • ๐ŸŽฃ Build your own customized autocomplete UI by React hook.
  • ๐Ÿ”ง Utility functions to do geocoding and get geographic coordinates using Google Maps Geocoding API.
  • ๐Ÿ’ฐ Built-in debounce mechanism for you to lower the cost of Google APIs.
  • ๐Ÿš€ Support asynchronous Google script loading.
  • ๐Ÿ“œ Support TypeScript type definition.
  • โŒจ๏ธ Build an UX rich component (e.g. WAI-ARIA compliant and keyword support) via comprehensive demo code.

Requirement

To use use-places-autocomplete, you must use [email protected] or greater which includes hooks.

Installation

This package is distributed via npm.

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

Getting Started

usePlacesAutocomplete is based on the Places Autocomplete (or more specific docs) of Google Maps Place API. If you are unfamiliar with these APIs, we recommend you reviewing 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 the script tag to load the library in your project.

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

We also support asynchronous script loading. By doing so you need to pass the initMap as the callbackName option.

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

โš ๏ธ If you got a global function not found error. Make sure usePlaceAutocomplete is declared before the script was loaded.

Create the component

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

import React, { useRef } from 'react';
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 = useRef();
  useOnclickOutside(ref, () => {
    // 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 as "false"
    setValue(description, false);
    clearSuggestions();

    // Get latitude and longitude via utility functions
    getGeocode({ address: description })
      .then(results => getLatLng(results[0]))
      .then(({ lat, lng }) => {
        console.log('๐Ÿ“ Coordinates: ', { lat, lng });
      }).catch(error => {
        console.log('๐Ÿ˜ฑ Error: ', error)
      });
  };

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

      return (
        <li
          key={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 an UX rich autocomplete component, like WAI-ARIA compliant and keyword support as my demo (check the code), a keyword clear button, search history etc.

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

API

const return = usePlacesAutocomplete(parameter);

Parameter object (optional)

When use usePlacesAutocomplete you can configure the following options via the parameter.

Key Type Default Description
requestOptions object The request options of Google Maps Places API except for input (e.g. bounds, radius etc.).
googleMaps object window.google.maps In case you want to provide your own Google Maps object, pass it in as google.maps.
callbackName string You can provide a callback name to initialize usePlacesAutocomplete after Google script is loaded. It's useful when you load the script asynchronously.
debounce number 200 Number of milliseconds to delay before making a request to Google Maps Places API.

Return object

It's returned with the following properties.

Key Type Default Description
ready boolean false The ready status of usePlacesAutocomplete.
value string '' value for the input element.
suggestions object { loading: false, status: '', data: [] } See suggestions.
setValue function (value, shouldFetchData = true) => {} See setValue.
clearSuggestions function See clearSuggestions.

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 completed. It's useful for displaying a loading indicator for user.
  • status: string - indicates the status of API response, which has these values. It's useful to decide whether we should display the dropdown or not.
  • data: array - an array of suggestion objects each contains all the data.

setValue

Set the value of the input element. Use case as below.

import React from 'react';
import usePlacesAutocomplete from 'use-places-autocomplete';

const PlacesAutocomplete = () => {
  const { value, setValue } = usePlacesAutocomplete();

  const handleInput = (e) => {
    // Place a "string" to update the value of the input element
    setValue(e.target.value);
  };

  return (
    <div>
      <input value={value} onChange={handleInput} />
      {/* Render dropdown */}
    </div>
  );
};

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

import React from 'react';
import usePlacesAutocomplete from 'use-places-autocomplete';

const PlacesAutocomplete = () => {
  const {
    value,
    suggestions: { status, data },
    setValue
  } = usePlacesAutocomplete();

  const handleSelect = ({ description }) => () => {
    // When user select a place, we can replace the keyword without request data from API
    // by setting the second parameter to "false"
    setValue(description, false);
  };

  const renderSuggestions = () =>
    data.map(suggestion => (
        <li
          key={suggestion.id}
          onClick={handleSelect(suggestion)}
        >
          {/* Render suggestion text */}
        </li>
      )
    });

  return (
    <div>
      <input value={value} onChange={handleInput} />
      {status === 'OK' && <ul>{renderSuggestions()}</ul>}
    </div>
  );
};

clearSuggestions

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

import React, { useRef } from 'react';
import usePlacesAutocomplete from 'use-places-autocomplete';
import useOnclickOutside from 'react-cool-onclickoutside';

const PlacesAutocomplete = () => {
  const {
    value,
    suggestions: { status, data },
    setValue,
    clearSuggestions
  } = usePlacesAutocomplete();
  const ref = useRef();
  useOnclickOutside(ref, () => {
    // When user clicks outside of the component, call it to clear and reset the suggestions data
    clearSuggestions();
  });

  const renderSuggestions = () =>
    data.map(suggestion => (
        <li
          key={suggestion.id}
          onClick={handleSelect(suggestion)}
        >
          {/* Render suggestion text */}
        </li>
      )
    });

  return (
    <div ref={ref}>
      <input value={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 provide getGeocode, getLatLng and getZipCode 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) by Google Maps Geocoding API.

import { getGeocode } from 'use-places-autocomplete';

const parameter = {
  address: 'Section 5, Xinyi Road, Xinyi District, Taipei City, Taiwan',
  // or
  placeId: '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 of address or placeId. It'll be passed as Geocoding Requests.
  • results: array - an array of objects each contains all the data.
  • error: string - the error status of API response, which has these values (except for "OK").

getLatLng

It helps you get the lat and lng from the result object of getGeocode.

import { getGeocode, getLatLng } from 'use-places-autocomplete';

const parameter = {
  address: 'Section 5, Xinyi Road, Xinyi District, Taipei City, Taiwan',
};

getGeocode(parameter)
  .then((results) => getLatLng(results[0]))
  .then((latLng) => {
    const { lat, lng } = latLng;

    console.log('Coordinates: ', { lat, lng });
  })
  .catch((error) => {
    console.log('Error: ', error);
  });

getLatLng is an asynchronous function with the following API:

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

getZipCode

It helps you get the postal_code from the result object of getGeocode.

import { getGeocode, getZipCode } from 'use-places-autocomplete';

const parameter = {
  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 as "true"
  .then((results) => getZipCode(results[0], false))
  .then((zipCode) => {
    console.log('ZIP Code: ', zipCode);
  })
  .catch((error) => {
    console.log('Error: ', error);
  });

getZipCode is an asynchronous function with the following API:

  • parameters - there're two parameters:
    • 1st: object - the result object of getGeocode.
    • 2nd: boolean - should use the short_name or not from API response, default is false.
  • zipCode: string | null - the zip code. If the address doesn't have zip code it will be null.
  • error: any - an exception.

Contributors โœจ

Thanks goes to these wonderful people (emoji key):


Welly

๐Ÿ’ป ๐Ÿ“– ๐Ÿšง

Kyle

๐ŸŒ

This project follows the all-contributors specification. Contributions of any kind welcome!

use-places-autocomplete's People

Contributors

wellyshen avatar dependabot-preview[bot] avatar allcontributors[bot] avatar kylekirkby avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.