Skip to content

Instantly share code, notes, and snippets.

@codyeatworld
Created July 11, 2019 19:58
Show Gist options
  • Save codyeatworld/793fa3e9bf25afaddd1675fb914542c1 to your computer and use it in GitHub Desktop.
Save codyeatworld/793fa3e9bf25afaddd1675fb914542c1 to your computer and use it in GitHub Desktop.
/* eslint-disable no-undef */
import { useEffect, useState, useRef } from 'react';
const useAutocomplete = () => {
// By using the `set` method of the `useState` hook, we can coax this into being `callback ref`
// contained inside of the hook.
const [autocompleteRef, setAutocompleteRef] = useState(null);
// We will return the formatted address with this const.
const [autocompletedAddress, setAutocompletedAddress] = useState(null);
// We only want one instance of the google places autocomplete method called using our callback
// ref. We can use a ref to store this instance across renders.
const autocomplete = useRef();
useEffect(() => {
// Since the autocompleteRef can be null, we need to make sure its ready.
if (autocompleteRef) {
// Use this listener callback to format an address object when the user selects an address
// from the autocomplete dropdown.
const onPlaceChanged = (ac) => () => {
// Get selected address results
const components = ac.getPlace().address_components;
// Initialize new address object
const address = {};
// Address type/name mapping
const mapping = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
postal_code: 'short_name',
};
// Format address values using mapping and results.
for (let i = 0; i < components.length; i++) {
const type = components[i].types[0];
if (mapping[type]) {
const value = components[i][mapping[type]];
address[type] = value;
}
};
// Set autocompleted/formatted address.
setAutocompletedAddress(address);
};
// Initialize google maps
autocomplete.current = new google.maps.places.Autocomplete(
autocompleteRef,
{
types: ['address'],
},
);
autocomplete.current.setFields(['address_component']);
autocomplete.current.addListener('place_changed', onPlaceChanged(autocomplete.current));
}
}, [autocompleteRef]);
// Return ref and address.
// We can react to the autocompletedAddress whenever it changes to do something with it.
// This allows this hook to be used on any form!
return [setAutocompleteRef, autocompletedAddress];
};
export default useAutocomplete;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment