Skip to content

Commit 59ac59e

Browse files
committed
add usePlacesService, share some functionality between modules, add minify babel, add google maps types (#100)
1 parent 1477ee2 commit 59ac59e

23 files changed

+4076
-487
lines changed

.babelrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"presets": ["es2015", "react", "stage-0"],
3-
}
2+
"presets": ["es2015", "react", "stage-0", "minify"]
3+
}

README.md

Lines changed: 147 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
![](/docs/example.gif)
22

3-
![](https://img.badgesize.io/ErrorPro/react-google-autocomplete/master/lib/index.js?compression=gzip&label=gzip)
4-
![](https://img.badgesize.io/ErrorPro/react-google-autocomplete/master/lib/index.js?compression=brotli&label=brotli)
5-
![](https://badgen.net/npm/dm/react-google-autocomplete?labelColor=49516F&color=8994BC)
3+
![](https://img.badgesize.io/ErrorPro/react-google-autocomplete/master/lib/ReactGoogleAutocomplete.js?compression=gzip&label=gzip)
4+
![](https://img.badgesize.io/ErrorPro/react-google-autocomplete/master/lib/ReactGoogleAutocomplete.js?compression=brotli&label=brotli)
5+
![](https://badgen.net/npm/dm/react-google-autocomplete)
66
[![GitHub license](https://img.shields.io/github/license/Naereen/StrapDown.js.svg)](https://GitHub.com/ErrorPro/react-google-autocomplete/master/LICENSE)
77

8-
## React google autocomplete
8+
## The package provides 3 tools for working with google places services:
99

10-
This is a simple react component for working with google [autocomplete](https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete)
10+
1. [ReactGoogleAutocomplete](#reactgoogleautocomplete) is a simple html input component that provides functionality of the [google places widgets](https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions).
11+
2. [usePlacesWidget](#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.
12+
3. [usePlacesAutocompleteService](#useplacesautocompleteservice) is a more complex tool. It uses [google places autocomplete service](https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service) and it provides all the functionality to you as the return value. In addition to that, you can set a `debounce` prop which will prevent users to send many requests to Google.
1113

1214
## Install
1315

@@ -26,6 +28,13 @@ As of version 1.2.4, you can now pass an `apiKey` prop to automatically load the
2628
apiKey={YOUR_GOOGLE_MAPS_API_KEY}
2729
onPlaceSelected={(place) => console.log(place)}
2830
/>
31+
or
32+
const { ref } = usePlacesWidget({
33+
apiKey: YOUR_GOOGLE_MAPS_API_KEY,
34+
onPlaceSelected: (place) => console.log(place)
35+
})
36+
37+
<AnyInput ref={ref} />
2938
```
3039

3140
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](https://developers.google.com/maps/documentation/places/web-service/autocomplete)
@@ -37,15 +46,28 @@ Alternatively if not passing the `apiKey` prop, you can include google autocompl
3746
></script>
3847
```
3948

40-
## Props
49+
## ReactGoogleAutocomplete
50+
51+
This is a simple react component for working with google [autocomplete](https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete)
52+
53+
```js
54+
import Autocomplete from "react-google-autocomplete";
55+
56+
<Autocomplete
57+
apiKey={YOUR_GOOGLE_MAPS_API_KEY}
58+
onPlaceSelected={(place) => {
59+
console.log(place);
60+
}}
61+
/>;
62+
```
63+
64+
### Props
4165

4266
- `apiKey`: pass to automatically load the Google maps scripts. The api key can be found in your [google cloud console.](https://developers.google.com/maps/documentation/javascript/get-api-key)
4367

4468
- `ref`: [React ref](https://reactjs.org/docs/hooks-reference.html#useref) to be assigned the underlying text input ref.
4569

46-
- `autocompleteRef`: [React ref](https://reactjs.org/docs/hooks-reference.html#useref) to be assigned the [google autocomplete instance](https://developers.google.com/maps/documentation/javascript/reference/places-widget#Autocomplete).
47-
48-
- `onPlaceSelected: (place: `[PlaceResult](https://developers.google.com/maps/documentation/javascript/reference/places-service#PlaceResult)`, inputRef, autocompleteRef) => void`: The function gets invoked every time a user chooses location.
70+
- `onPlaceSelected: (place: `[PlaceResult](https://developers.google.com/maps/documentation/javascript/reference/places-service#PlaceResult)`, inputRef, `[autocompleteRef](https://developers.google.com/maps/documentation/javascript/reference/places-widget#Autocomplete)`) => void`: The function gets invoked every time a user chooses location.
4971

5072
- `options`: [Google autocomplete options.](https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions)
5173

@@ -60,6 +82,86 @@ Alternatively if not passing the `apiKey` prop, you can include google autocompl
6082

6183
You can pass any prop specified for the hmtl [input tag](https://www.w3schools.com/tags/tag_input.asp). You can also set [options.fields](https://developers.google.com/maps/documentation/javascript/reference/places-service#PlaceResult) prop if you need extra information, now it defaults to basic data in order to control expenses.
6284

85+
## usePlacesWidget
86+
87+
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.
88+
89+
```js
90+
import { usePlacesWidget } from "react-google-autocomplete";
91+
92+
export default () => {
93+
const { ref, autocompleteRef } = usePlacesWidget({
94+
apiKey:YOUR_GOOGLE_MAPS_API_KEY,
95+
onPlaceSelected: (place) => {
96+
console.log(place);
97+
}
98+
});
99+
100+
return <AnyInput ref={ref} {...anyOtherProp}>
101+
}
102+
```
103+
104+
### Arguments
105+
106+
It has only one config argument which has propperties: `apiKey`, `ref`, `onPlaceSelected`, `options`, `inputAutocompleteValue`, `googleMapsScriptBaseUrl`. The same props described [here](#reactgoogleautocomplete)
107+
108+
## usePlacesAutocompleteService
109+
110+
![](https://img.badgesize.io/ErrorPro/react-google-autocomplete/master/lib/usePlacesAutocompleteService.js?compression=brotli&label=brotli)
111+
![](https://img.badgesize.io/ErrorPro/react-google-autocomplete/master/lib/usePlacesAutocompleteService.js?compression=gzip&label=gzip)
112+
113+
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.
114+
115+
```js
116+
import usePlacesService from "react-google-autocomplete/lib/usePlacesAutocompleteService";
117+
118+
export default () => {
119+
const {
120+
placePredictions,
121+
getPlacePredictions,
122+
isPlacePredictionsLoading,
123+
} = useGoogle({
124+
apiKey: process.env.REACT_APP_GOOGLE,
125+
});
126+
127+
return (
128+
<>
129+
<Input
130+
placeholder="Debounce 500 ms"
131+
onChange={(evt) => {
132+
getPlacePredictions({ input: evt.target.value });
133+
}}
134+
loading={isPlacePredictionsLoading}
135+
/>
136+
{placePredictions.map((item) => renderItem(item))}
137+
</>
138+
);
139+
};
140+
```
141+
142+
[example](/docs/debounce.js)
143+
144+
### Arguments
145+
146+
The hook has only one config argument.
147+
148+
- `config`:
149+
- `apiKey`: Google api key, otherwise google api has to be loaded manually.
150+
- `googleMapsScriptBaseUrl`: Provide custom google maps url. By default `https://maps.googleapis.com/maps/api/js`.
151+
- `debounce`: Number of milliseconds to accumulate responses for.
152+
- `options`: Default [options](https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#QueryAutocompletionRequest) which will be passed to every request.
153+
154+
### Returned value
155+
156+
The hook returns an object with properties:
157+
158+
- `placePredictions`: an array of [AutocompletePrediction](https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#AutocompleteResponse)
159+
- `isPlacePredictionsLoading`: sets to true when a `getPlacePredictions` request is being sent and not yet resolved.
160+
- `getPlacePredictions: (opt: `[Options](https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#AutocompletionRequest)`): void`: a function which you call whenever you want to request places predictions. Takes one [argument](https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#AutocompleteResponse).
161+
- `queryPredictions`: an array of [QueryAutocompletePrediction](https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#QueryAutocompletePrediction)
162+
- `isQueryPredictionsLoading`: sets to true when `getQueryPredictions` request is being sent and not yet resolved.
163+
- `getQueryPredictions: (opt: `[Options](https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#QueryAutocompletionRequest)`): void`: a function which you call whenever you want to request query predictions. Takes one [argument](https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#QueryAutocompletionRequest).
164+
63165
## Examples
64166

65167
### Simple autocomplete with options
@@ -81,61 +183,65 @@ import Autocomplete from "react-google-autocomplete";
81183
/>;
82184
```
83185

84-
### Passing refs
186+
or
85187

86188
```js
87-
import Autocomplete from "react-google-autocomplete";
88-
89-
const inputRef = useRef(null);
189+
import { usePlacesWidget } from "react-google-autocomplete";
190+
191+
export default () => {
192+
const { ref } = usePlacesWidget({
193+
apiKey: YOUR_GOOGLE_MAPS_API_KEY,
194+
onPlaceSelected: (place) => {
195+
console.log(place);
196+
},
197+
options: {
198+
types: ["(regions)"],
199+
componentRestrictions: { country: "ru" },
200+
},
201+
});
202+
203+
return <input ref={ref} style={{ width: "90%" }} defaultValue="Amsterdam" />;
204+
};
205+
```
90206

91-
useEffect(() => {
92-
// focus on mount
93-
inputRef.current.focus()
94-
}, [])
207+
### Getting access to the google autocomplete instance
95208

209+
```js
96210
<Autocomplete
97-
ref={inputRef}
98-
onPlaceSelected={(place) => {
99-
console.log(place);
211+
onPlaceSelected={(place, inputRef, autocomplete) => {
212+
console.log(autocomplete);
100213
}}
101-
/>;
102-
214+
/>
103215
```
104216

105-
### Getting access to the google autocomplete instance
217+
or
106218

107219
```js
108-
import Autocomplete from "react-google-autocomplete";
109-
110-
const autocompleteRef = useRef(null);
111-
112-
<Autocomplete
113-
autocompleteRef={autocompleteRef}
114-
onPlaceSelected={(place, inputRef, theSameAutocompletRef) => {
220+
const { ref, autocompleteRef } = usePlacesWidget({
221+
apiKey: YOUR_GOOGLE_MAPS_API_KEY,
222+
onPlaceSelected: (place) => {
115223
console.log(place);
116-
}}
117-
/>;
118-
119-
<button onClick={() => autocompleteRef.current.getPlace()}>Read place</button>;
224+
},
225+
});
120226
```
121227

122-
### Typescript
228+
### More examples(dynamic props, MaterialUI, Ant, Bootstrap) could be found in [docs/examples.js](/docs/examples.js)
123229

124-
We are planning on rewritting the library with TS/Flow in the later releases but you can already use it with TypeScript.
230+
Formik example lives [here](/docs/formik.js)
125231

126-
```ts
127-
import Autocomplete from "react-google-autocomplete";
232+
Debounce example lives [here](/docs/debounce.js)
128233

129-
<Autocomplete apiKey="123" />;
130-
```
234+
### Typescript
131235

132-
More examples(dynamic props, MaterialUI) how to use the lib could be found in `docs/examples.js`
236+
We are planning on rewriting the library with TS/Flow in the later releases but you can already use it with TypeScript bacause we use [declaration files](https://www.typescriptlang.org/docs/handbook/declaration-files/dts-from-js.html).
133237

134238
### TODO
135239

136240
- Check that it fully works with SSR
241+
- Add more UI libraries examples/supports
137242
- Add eslint config(base-airbnb)
138243
- Rewrite the lib to TS and add flow support
244+
- Remove lodash and use own built-in solution for debouncing
139245

140246
## Contribution
141247

docs/debounce.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { useState } from "react";
2+
import { Input, List } from "antd";
3+
4+
import useGoogle from "react-google-autocomplete/lib/usePlacesAutocompleteService";
5+
6+
export const Debounce = ({ a }) => {
7+
const {
8+
placePredictions,
9+
getPlacePredictions,
10+
isPlacePredictionsLoading,
11+
} = useGoogle({
12+
apiKey: process.env.REACT_APP_GOOGLE,
13+
});
14+
const [value, setValue] = useState("");
15+
16+
return (
17+
<div style={{ width: "250px" }}>
18+
<span>Debounced</span>
19+
<Input.Search
20+
style={{ color: "black" }}
21+
value={value}
22+
placeholder="Debounce 500 ms"
23+
onChange={(evt) => {
24+
getPlacePredictions({ input: evt.target.value });
25+
setValue(evt.target.value);
26+
}}
27+
loading={isPlacePredictionsLoading}
28+
/>
29+
<div
30+
style={{
31+
marginTop: "20px",
32+
width: "200px",
33+
height: "200px",
34+
display: "flex",
35+
flex: "1",
36+
flexDirection: "column",
37+
marginBottom: "100px",
38+
}}
39+
>
40+
{!isPlacePredictionsLoading && (
41+
<List
42+
dataSource={placePredictions}
43+
renderItem={(item) => (
44+
<List.Item onClick={() => setValue(item.description)}>
45+
<List.Item.Meta title={item.description} />
46+
</List.Item>
47+
)}
48+
/>
49+
)}
50+
</div>
51+
</div>
52+
);
53+
};

docs/example.gif

133 KB
Loading

0 commit comments

Comments
 (0)