Reputation: 343
I have managed to get list of google place predictions using google.maps.places.AutocompleteService() and when i print one prediction in console, i get output as given below:
But this information of place is not enough because i wanted place info as given below:
Now by using place_id, i have fetched placedetails using service google.map.places.PlacesService.getDetails
predictionSelected = (prediction) => {
let placeDetails= this.googlePlaces.getDetails(
{ placeId: prediction.place_id },
function (results, status) {
console.log(results);
return results;
}
);
console.log(placeDetails); // results undefined
}
Now the issue is that i am not able to use this.state inside getDetails so i tried to return results. Since getDetails is async, i am not able return results properly.
Is there anyway to use this.state inside getDetails or wait till response comes and do actions below after async response ?
Here is all my class
import React from "react";
/* global google */
export default class AddressPredictionsClass extends React.Component {
constructor(props) {
super(props);
this.componentForm = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
postal_code: 'short_name'
};
this.state = {
street_number: '',
route: '',
locality: '',
administrative_area_level_1: '',
postal_code: '',
is_disabled: true,
is_search_disabled: false,
predictions: [],
suggestions: [],
text: '',
setIndex: -1
};
/** preserve initial state */
this.baseState = this.state;
this.autocompleteService = React.createRef();
this.googlePlaces = '';
this.onKeyDown = this.onKeyDown.bind(this);
}
onKeyDown = (e) => {
/** some code **/
}
componentDidMount() {
if (!this.autocompleteService.current) {
this.autocompleteService.current = new google.maps.places.AutocompleteService();
}
let map = new google.maps.Map(document.createElement('div'));
this.googlePlaces = new google.maps.places.PlacesService(map);
}
getPlacePredictions = (input) => {
if (input === null) {
console.log('null input');
return false;
}
var request = {
input: input,
componentRestrictions: { country: 'au' },
types: ["geocode"]
}
this.autocompleteService.current.getPlacePredictions(
request,
predictions => {
if (predictions === null) {
this.setState(
{ predictions: [] }
)
} else {
this.setState(
{ predictions: predictions.map(prediction => prediction) }
)
}
}
);
}
predictionSelected = (prediction) => {
let placeDetails=this.googlePlaces.getDetails(
{ placeId: prediction.place_id },
function (results, status) {
return results;
}
);
console.log(placeDetails);
}
changeStateValue(type, val) {
/** some code **/
}
}
onChange = (e) => {
/** some code **/
}
renderSuggestions() {
/** some code **/
}
render() {
return (
<div>
<table id="address">
<tbody>
<tr>
<td className="">Street address</td>
<td className="">
<input onChange={event => this.getPlacePredictions(event.target.value)} className=""/>
{this.renderSuggestions()}
</td>
</tr>
</tbody>
</table>
</div>
);
}
}
Upvotes: 1
Views: 1729
Reputation: 5699
You can still do it with this.state
. Check out the code below:
import React from "react";
import "./styles.css";
/* global google */
export default class App extends React.Component {
constructor(props) {
super(props);
this.componentForm = {
street_number: "short_name",
route: "long_name",
locality: "long_name",
administrative_area_level_1: "short_name",
postal_code: "short_name"
};
this.state = {
street_number: "",
route: "",
locality: "",
administrative_area_level_1: "",
postal_code: "",
is_disabled: true,
is_search_disabled: false,
predictions: [],
suggestions: [],
text: "",
setIndex: -1
};
/** preserve initial state */
this.baseState = this.state;
this.autocompleteService = React.createRef();
this.googlePlaces = "";
this.onKeyDown = this.onKeyDown.bind(this);
}
onKeyDown = e => {
/** some code **/
};
componentDidMount() {
if (!this.autocompleteService.current) {
this.autocompleteService.current = new google.maps.places.AutocompleteService();
}
let map = new google.maps.Map(document.createElement("div"));
this.googlePlaces = new google.maps.places.PlacesService(map);
}
getPlacePredictions = input => {
if (input === null) {
console.log("null input");
return false;
}
var request = {
input: input,
componentRestrictions: { country: "au" },
types: ["geocode"]
};
this.autocompleteService.current.getPlacePredictions(
request,
predictions => {
if (predictions === null) {
this.setState({ predictions: [] });
} else {
this.setState({
predictions: predictions.map(prediction => prediction)
});
this.predictionSelected(this.state.predictions);
}
}
);
};
predictionSelected = predictions => {
const places = [];
for (let prediction of predictions) {
this.googlePlaces.getDetails({ placeId: prediction.place_id }, function (
place,
status
) {
places.push(place);
});
}
this.setState({
...this.state,
places: places
});
};
renderSuggestions = () => {
console.log(
"predictions",
this.state.predictions.map(prediction => prediction)
);
if (this.state.places && this.state.places.length) {
console.log("places", this.state.places.map(place => place));
}
};
render() {
return (
<div>
<table id="address">
<tbody>
<tr>
<td className="">Street address</td>
<td className="">
<input
onChange={event =>
this.getPlacePredictions(event.target.value)
}
className=""
/>
{this.renderSuggestions()}
</td>
</tr>
</tbody>
</table>
</div>
);
}
}
And here's a working codesandbox. Make sure you add your API key in index.html first.
Hope this helps!
Upvotes: 1