Giter Site home page Giter Site logo

errorpro / react-google-autocomplete Goto Github PK

View Code? Open in Web Editor NEW
452.0 9.0 109.0 1.06 MB

React components for google places API.

License: MIT License

JavaScript 100.00%
google-autocomplete react reactjs places google-places google-api google-places-widget google-places-autocomplete google-places-service google-places-debounce

react-google-autocomplete's Introduction

GitHub license

The package provides 3 tools for working with google places services:

  1. ReactGoogleAutocomplete is a simple html input component that provides functionality of the google places widgets.
  2. usePlacesWidget is a react hook that provides the same functionality as ReactGoogleAutocomplete does but it does not create any dom elements. Instead, it gives you back a react ref which you can set to any input you want.
  3. usePlacesAutocompleteService is a more complex react hook. It uses google places autocomplete service and it provides all the functionality to you as the returned value. In addition to that, you can set a debounce prop which will reduce the amount of requests users send to Google.

If you find this package helpful please give it a star because it hepls it grow and motivates us to build new features and support the old ones.

Install

npm i react-google-autocomplete --save

or

yarn add react-google-autocomplete


As of version 1.2.4, you can now pass an apiKey prop to automatically load the Google maps scripts. The api key can be found in your google cloud console.

<Autocomplete
  apiKey={YOUR_GOOGLE_MAPS_API_KEY}
  onPlaceSelected={(place) => console.log(place)}
/>
or
const { ref } = usePlacesWidget({
  apiKey: YOUR_GOOGLE_MAPS_API_KEY,
  onPlaceSelected: (place) => console.log(place)
})

<AnyInput ref={ref} />

Alternatively if not passing the apiKey prop, you can include google autocomplete link api in your app. Somewhere in index.html or somewhere else. More info here

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

ReactGoogleAutocomplete

This is a simple react component for working with google autocomplete

import Autocomplete from "react-google-autocomplete";

<Autocomplete
  apiKey={YOUR_GOOGLE_MAPS_API_KEY}
  onPlaceSelected={(place) => {
    console.log(place);
  }}
/>;

Props

  • apiKey: pass to automatically load the Google maps scripts. The api key can be found in your google cloud console.

  • ref: React ref to be assigned the underlying text input ref.

  • onPlaceSelected: (place: PlaceResult, inputRef, autocompleteRef) => void: The function gets invoked every time a user chooses location.

  • options: Google autocomplete options.

    • options.types: By default it uses (cities).
    • options.fields: By default it uses address_components, geometry.location, place_id, formatted_address.
  • inputAutocompleteValue: Autocomplete value to be set to the underlying input.

  • googleMapsScriptBaseUrl: Provide custom google maps url. By default https://maps.googleapis.com/maps/api/js

  • defaultValue prop is used for setting up the default value e.g defaultValue={'Amsterdam'}.

  • language: Set language to be used for the results. If not specified, Google defaults to load the most appropriate language based on the users location or browser setting.

  • libraries: prop is used for loading additional google libraries alongside the places api, defaultValue={["places"]}.

You can pass any prop specified for the hmtl input tag. You can also set options.fields prop if you need extra information, now it defaults to basic data in order to control expenses.

usePlacesWidget

Is a hook that has a single config argument. It has exactly the same interface as ReactGoogleAutocomplete props. This hook is actually used in the ReactGoogleAutocomplete component.

import { usePlacesWidget } from "react-google-autocomplete";

export default () => {
  const { ref, autocompleteRef } = usePlacesWidget({
    apiKey:YOUR_GOOGLE_MAPS_API_KEY,
    onPlaceSelected: (place) => {
      console.log(place);
    }
  });

  return <AnyInput ref={ref} {...anyOtherProp}>
}

Arguments

It has only one config argument which has propperties: apiKey, ref, onPlaceSelected, options, inputAutocompleteValue, googleMapsScriptBaseUrl. The same props described here

Returned value

This hook returns object with only two properties:

  • ref - is a react ref which you can assign to any input you would like.
  • autocompleteRef - is the autocomplete instance

usePlacesAutocompleteService

This is an initial implementation of debounced google places autocomplete service. It gives you an option to reduce the amount of requests sent to google which reduce your costs. For the time being we decided to use lodash.debounce to save time and in the later versions we might write our own implementation of debounce with hooks. Because it uses lodash we also decided to not put it into the index library file so it lives in its own file and could be only imported by it.

import usePlacesService from "react-google-autocomplete/lib/usePlacesAutocompleteService";

export default () => {
  const {
    placesService,
    placePredictions,
    getPlacePredictions,
    isPlacePredictionsLoading,
  } = usePlacesService({
    apiKey: process.env.REACT_APP_GOOGLE,
  });

  useEffect(() => {
    // fetch place details for the first element in placePredictions array
    if (placePredictions.length)
      placesService?.getDetails(
        {
          placeId: placePredictions[0].place_id,
        },
        (placeDetails) => savePlaceDetailsToState(placeDetails)
      );
  }, [placePredictions]);

  return (
    <>
      <Input
        placeholder="Debounce 500 ms"
        onChange={(evt) => {
          getPlacePredictions({ input: evt.target.value });
        }}
        loading={isPlacePredictionsLoading}
      />
      {placePredictions.map((item) => renderItem(item))}
    </>
  );
};

example

Arguments

The hook has only one config argument.

  • config:
    • apiKey: Google api key, otherwise google api has to be loaded manually.
    • googleMapsScriptBaseUrl: Provide custom google maps url. By default https://maps.googleapis.com/maps/api/js.
    • debounce: Number of milliseconds to accumulate responses for.
    • options: Default options which will be passed to every request.
    • sessionToken: If true then a session token will be attached to every request.
    • language: If the language code is set, the results will be returned in the specificed language
    • libraries: prop is used for loading additional google libraries alongside the places api, defaultValue={["places"]}.

Returned value

The hook returns an object with properties:

Examples

Simple autocomplete with options

import Autocomplete from "react-google-autocomplete";

<Autocomplete
  apiKey={YOUR_GOOGLE_MAPS_API_KEY}
  style={{ width: "90%" }}
  onPlaceSelected={(place) => {
    console.log(place);
  }}
  options={{
    types: ["(regions)"],
    componentRestrictions: { country: "ru" },
  }}
  defaultValue="Amsterdam"
/>;

or

import { usePlacesWidget } from "react-google-autocomplete";

export default () => {
  const { ref } = usePlacesWidget({
    apiKey: YOUR_GOOGLE_MAPS_API_KEY,
    onPlaceSelected: (place) => {
      console.log(place);
    },
    options: {
      types: ["(regions)"],
      componentRestrictions: { country: "ru" },
    },
  });

  return <input ref={ref} style={{ width: "90%" }} defaultValue="Amsterdam" />;
};

Getting access to the google autocomplete instance

<Autocomplete
  onPlaceSelected={(place, inputRef, autocomplete) => {
    console.log(autocomplete);
  }}
/>

or

const { ref, autocompleteRef } = usePlacesWidget({
  apiKey: YOUR_GOOGLE_MAPS_API_KEY,
  onPlaceSelected: (place) => {
    console.log(place);
  },
});

More examples(dynamic props, MaterialUI, Ant, Bootstrap) could be found in docs/examples.js

Formik example lives here

Debounce example lives here

Typescript

We are planning on rewriting the library with TS/Flow in the later releases but you can already use it with TypeScript because we use declaration files.

TODO

  • Check that it fully works with SSR Fully works with SSR: tested with: Next.js, Gatsby.js and custom SSR based on Express.js.
  • Add more UI libraries examples/supports
  • Add eslint config(base-airbnb)
  • Rewrite the lib to TS and add flow support
  • Remove lodash and use own built-in solution for debouncing

Troubleshooting

  • You have included the Google Maps JavaScript API multiple times on this page. Solution

Contribution

If you would like to see something in this library please create an issue and I will implement it as soon as possible.

react-google-autocomplete's People

Contributors

adriandmitroca avatar anenth avatar arcdev1 avatar caaatisgood avatar clementineoldfield avatar dependabot[bot] avatar errorpro avatar herebefrogs avatar jeanlucmongrain avatar juanzgc avatar katanis avatar kevinparkerson avatar lacunadream avatar lloydwatkin avatar matvaleriano avatar niranjanv849 avatar nwmahoney avatar p-schlickmann avatar panvourtsis avatar patdx avatar riley-brown avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-google-autocomplete's Issues

InvalidValueError: not an instance of HTMLInputElement

I am developing an application, in Ionic, where you can plan a trip with a start address and an end address. However, I want to limit this feature to only one country. Before writing I have been searching for solutions on the internet, but none of them worked for me.

Have tried these suggestions:

https://stackoverflow.com/a/8282093/8130808

https://stackoverflow.com/a/10170421/8130808

Here is how I have tried to approach it:

I get the input from an alert dialog

newRouteInput() {

let alert = this.alertCtrl.create({
  title: 'New route',
  inputs: [
    {
      name: 'routeStart',
      placeholder: 'Start of route'
    },
    {
      name: 'routeEnd',
      placeholder: 'End of route'
    }
  ],
  buttons: [
    {
      text: 'Cancel',
      role: 'cancel',
      handler: data => {
        console.log('Cancel clicked');
      }
    },
    {
      text: 'Debug start and end',
      handler: data => {
        if (data.username !== "undefined") {
          console.log(data.routeStart + " " + data.routeEnd);
          this.routeStart = "Malmö";
          this.routeEnd = "Berlin";
          this.newRoutePlaceMarks(this.map);
          this.routeButton = false;

        } else {
          return false;
        }
        var input = document.getElementById(data.routeStart + " " + data.routeEnd);
        var autocomplete = new google.maps.places.Autocomplete(input);
        google.maps.event.addDomListener(input);
      }
    },
    {
      text: 'Place route markers',
      handler: data => {
        if (data.username !== "undefined") {
          this.routeStart = data.routeStart;
          this.routeEnd = data.routeEnd;
          this.newRoutePlaceMarks(this.map);
          this.routeButton = false;
        } else {
          console.log(data.routeStart + " " + data.routeEnd);
          return false;
          var input = document.getElementById(data.routeStart + " " + data.routeEnd);
        var autocomplete = new google.maps.places.Autocomplete(input);
        google.maps.event.addDomListener(input);
        }
      }
    }
  ]
});
alert.present();
 }

When I run this I get an error because of data.routeStart + " " + data.routeEnd. What's the solution? :)

componentRestrictions

Is it possible to set componentRestrictions for example I only want to show a specific country.

Future changes and things you'd change or add.

Hi. Here is a list of changes we are going to make eventually. Feel free to comment on anything you have in your mind.

  1. Passing a config object as a props to the component(@chexxor). #12 Done in v2.0.0
  2. Remove event listeners from the component when it gets unmounted . Done.
  3. Try to add google place service itself. As separated export. Done

Add address type to this component

Hello,
I am trying to use this autocomplete component. For now this is only suggesting cities as types = cities is hardcoded. Can this be extended for 'address' type?

Pass entire config object to the autocomplete?

Here: https://github.com/ErrorPro/react-google-autocomplete/blob/master/src/index.js#L19-L23

Instead of constructing this config object, can we pass it into the component through an attribute? The structure of this object is defined by Google, so this library only increases its maintenance burden by also knowing how to correctly create this config object. I imagine Google will be changing the options on this option in the future, so I want to avoid forcing us to make a new commit and new release of this library to support the new options.

If you think it's not a bad idea, I can make a PR.

Cannot read property 'remove' of null (on unmount)

Officially putting in an issue for documentation purposes. Please accept our PR as a fix #56. Thank you!

We are seeing a sporadic issue in production and have narrowed down the source to this line from our Honeybadger reports. Hopefully this will help others as well.

Honeybadger backtrace:
image

remove default value for types props

is there any rationale behind making the types props to be defaulted to (cities)? Can it not me made optional like bounds and componentRestrictions

I recently stumbled upon a requirement that allows me to consider all the autocomplete suggestions
According to google docs,

If nothing is specified, all types are returned

https://developers.google.com/places/web-service/autocomplete#place_types

Edit : I can make it work using this code block, passing the types as empty array


<Autocomplete
    style={{width: '90%'}}
    onPlaceSelected={(place) => {
      console.log(place);
    }}
    types={[]}
    componentRestrictions={{country: "ru"}}
/>

suggestions not displayed in the form

I am using this inside the form.

Some times it displays the suggestions, but sometimes it won't.

especially if the user entered some information in the other input fields of the form.

no action on pressing enter

i want to know if on pressing enter is it possible to search the position. we have only onPlaceSelected funtion to work with.

Establishment Support

is it possible to get input text of Establishment ? my code

<Autocomplete
    style={{width: '100%'}}
    placeholder="Input Establishment Name"
    onPlaceSelected={(place) => {
        console.log(place)
    }}
    types={['establishment',]}
    componentRestrictions={{country: "lk"}}
    name="place_name"
    value={this.state.place_name}
    onChange={this.handleInputChange}
/>

image

Input name not there :( only returning this
image
help needed

License

Please add a license to this project.

This module is very useful but I'd like some clarity in knowing the license to the project. The pull request of adding placeTypes would be make this extremely useful.

Get Latitute and Longitude

Hello. I am using your autocomplete in my application and it's working very well, but I would like to know how I can get the Latitude and Longitude of the selected place. The data seems to be under geometry->location->lat->[[Scopes]][0] but I cannot access the data in [[Scopes]]. How would I get the latitude and longitude?

Google chrome autofill is displayed over autocomplete results

Cant get chrome autofill to disappear:
image

Here is what the code looks like. I am using it with redux-form and autofill three hidden fields based on selection.

<Autocomplete
        onPlaceSelected={(place) => {
          autofill('address', place.formatted_address);
          autofill('coordinates.latitude', place.geometry.location.lat().toString());
          autofill('coordinates.longitude', place.geometry.location.lng().toString());
        }}
        types={['establishment', 'geocode']}
        className="form-control"
        placeholder="Number Street, City, State, Country"
        autoComplete="address-autocomplete"
        {...input}
        onKeyPress={e => {
          if (e.key === 'Enter') e.preventDefault();
        }}
      />

any help would be greatly appreciated.

Reset field ?

I'm using this inside filters, Now I need to reset location to empty when clicked clear filter button, any idea.

Change placeholder of input

Hello ,
I was trying to change the default input placeholder , is there any chance to have an attribute for that please?

Thanks
Aziz

null is not an object (evaluating 'this.event.remove')

👋 We are seeing 359 occurrences in production with the error: null is not an object (evaluating 'this.event.remove'). We were using version 1.1.0 of this library and will be upgrading to latest as soon as possible.

I am submitting a PR shortly to defensively check for the existence of this.autocomplete.

image

Initialize input with a place

Is there a way to initialize the input with a place? I set it to the full address text of the place right now, but it doesn't do a lookup onmount.

How to set bounds?

Hey, I am using this module in my app but I am unable to set the bounds for a search. Do you have a written code example of bounds usage in this module?

Use the prop-types package

Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead

Error when running webpack -p command

I don't know if someone here has the solution to my problem but when I run webpack-dev-server everything works as expected but when I run webpack -p I don't see any errors but the component doesn't show up.

Here are some of my dependencies :
"react": "^15.4.1",
"react-dom": "^15.4.1",
"react-google-autocomplete": "^1.0.11",
"react-tap-event-plugin": "^2.0.1",
"material-ui": "^0.16.4"

I tried a lot of thing but it's only when I remove <Autocomplete onPlaceSelected={(place) => { console.log(place); }} types={['address']} style={ inputStyle } /> that I can get a working code, and I have nothing logged to tell me where is the error...

Do you have any ideas ? Let me know if you need more informations

Any possibility to manually change the value ?

Hi,

I would know if there is a possibility to manually change the value which is shown in the textfield ? Or to bind it.

I work with the map and for some reason i would let people to choice between search for an adresse through your autocomplete component or by clicking on the map.

Best regard

No `setFields` config option

There is no clear exposed API for setting the fields on the Autocomplete instance. This is not ideal, as someone using this library might not realize google includes all fields by default, charging you for the additional apis that those fields may involve. To put it into context, someone who definitely isn't me used this in production and was charged $1400 for places API (expected) and an additional $700 for "atmosphere" and "contacts" data (unexpected)

For such an important configuration, there should be a first-class configuration option to handle this.

Currently, I have a ref on the input and am able to add my own config this way:

   componentDidMount() {
    this.inputRef.current.autocomplete.setFields(['formatted_address', etc.])
  }

React Ref Issue

With the most recent version @1.0.17, we are seeing a new error pop up:

Uncaught TypeError: Cannot set property 'autocomplete' of undefined

Without diving in too much it looks like the ref on line 41 of index.js isn't being set or accessed properly. Any help would be fantastic.

Publish a new version

Can you publish a new version?

I see that you removed the <div> here that used to wrap the <input>.

This update would be useful as the extra div is annoying as I have to take it into account when styling this component.

Styling autocomplete as per Material-UI design

Hi,
Has anyone been able to change the field styling as per material-ui styles? I have found the following link which explains all the relevant classes but it is being quite a mess to achieve it.
Any clues and answers would be very welcome!
Cheers.
Alejandro.

how to include multiple types on search.?

Hi,
I am using react-google-autocomplete but when i search i need to get

(regions)
establishment

types can anyone tell me how to include more than one types in that component.?

getting error while initialization

while I'm initialization I'm getting following error

InvalidValueError: setComponentRestrictions: in property country: not a string; and not an Array

following is the initialization code.

 <Autocomplete
                className="location-autofill"
                onPlaceSelected={(place) => {
                    props.formatLocationAddress(place);
                }}
                types={[]}
            />

Styling not compatible with CSS modules

When I try to style the component with Bootstrap (in accordance with best practices for globally-scoped CSS using CSS modules), nothing happens.

<Autocomplete className="input-group" /> renders the same as <Autocomplete />

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.