getPlace 函数不适用于 Google 自动完成反应
getPlace function not working with Google Autocomplete in react
我正在尝试在 React 中重新创建这个 Google 自动完成示例:https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressform
我正在使用本教程生成正确加载 Google API 所需的高阶组件:https://www.fullstackreact.com/articles/how-to-write-a-google-maps-react-component/
自动完成功能似乎工作正常。但是,当我 select 一个建议并尝试 运行 fillInAddress()
这是我得到的错误消息:
Uncaught TypeError: Cannot read property 'getPlace' of undefined
这是我的代码
/components/GoogleApiComponent.jsx
import React from 'react';
import {GoogleApiWrapper} from 'google-maps-react';
import GoogleAutoComplete from '../components/GoogleAutoComplete';
export class Container extends React.Component {
render() {
if (!this.props.loaded) {
return <div>Loading...</div>
}
return (
<div>
<GoogleAutoComplete
/>
</div>
)
}
}
export default GoogleApiWrapper({
apiKey: 'somekey'
})(Container)
../components/GoogleAutoComplete.jsx
import React from 'react';
export default class GoogleAutoComplete extends React.Component {
static propTypes = {
}
constructor(props) {
super(props);
}
componentDidMount() {
this.initAutocomplete();
}
initAutocomplete() {
this.autocomplete = new google.maps.places.Autocomplete((this.refs.autoCompletePlaces), {types: ['geocode']});
this.autocomplete.addListener('place_changed', this.fillInAddress);
}
geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
const geolocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
});
}
}
fillInAddress() {
const componentForm = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name',
postal_code: 'short_name'
};
// Get the place details from the autocomplete object.
const place = this.autocomplete.getPlace();
for (let component in componentForm) {
this.refs.component.value = '';
this.refs.component.disabled = false;
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (let i = 0; i < place.address_components.length; i++) {
const addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
const val = place.address_components[i][componentForm[addressType]];
this.refs.addressType.value = val;
}
}
}
render() {
return (
<div>
<div>
<input
placeholder="Enter your address"
onFocus={this.geolocate}
ref="autoCompletePlaces"
/>
</div>
<table ref="address">
<tbody>
<tr>
<td>Street address</td>
<td>
<input
ref="street_number"
disabled="true"/>
</td>
<td>
<input
ref="route"
disabled="true"/>
</td>
</tr>
<tr>
<td>City</td>
<td>
<input
ref="locality"
disabled="true"/>
</td>
</tr>
<tr>
<td>State</td>
<td>
<input
ref="administrative_area_level_1"
disabled="true"/>
</td>
<td>Zip code</td>
<td>
<input
ref="postal_code"
disabled="true"/>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<input
ref="country"
disabled="true"/>
</td>
</tr>
</tbody>
</table>
</div>
);
}
}
我在 discord, and this other 的人的帮助下解决了这个问题。根据该答案,关键点是 "Inside the place_changed-callback the keyword this points to the object which has been triggered the event."。我进行了更改并且它起作用了。
这是关键线:
this.place = this.autocomplete.getPlace();
为了完整起见,我还重构了表单填写
this.place.address_components.forEach((组件, 索引) => {
const addressType = this.place.address_components[index].types[0];
if (componentForm[addressType]) {
const val = this.place.address_components[index][componentForm[addressType]];
this.refs[addressType].value = val;
}
})
完整代码如下:
import React from 'react';
export default class GoogleAutoComplete extends React.Component {
static propTypes = {
}
constructor(props) {
super(props);
this.fillInAddress = this.fillInAddress.bind(this);
}
componentDidMount() {
this.initAutocomplete();
}
initAutocomplete() {
const google = window.google;
this.autocomplete = new google.maps.places.Autocomplete((this.refs.autoCompletePlaces), {types: ['geocode']});
this.autocomplete.addListener('place_changed', this.fillInAddress);
}
geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
const geolocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
});
}
}
fillInAddress() {
const componentForm = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name',
postal_code: 'short_name'
};
// Get the place details from the autocomplete object.
this.place = this.autocomplete.getPlace();
/*this.setState({placeResult: this.place.address_components})*/
for (let component in this.componentForm) {
this.refs.component.value = '';
this.refs.component.disabled = false;
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
this.place.address_components.forEach((component, index) => {
const addressType = this.place.address_components[index].types[0];
if (componentForm[addressType]) {
const val = this.place.address_components[index][componentForm[addressType]];
this.refs[addressType].value = val;
}
})
}
render() {
return (
<div>
<div>
<input
placeholder="Enter your address"
onFocus={this.geolocate}
ref="autoCompletePlaces"
className="form-control"
type="text"
/>
</div>
<table ref="address">
<tbody>
<tr>
<td>Street address</td>
<td>
<input
ref="street_number"
disabled="true"
value=''
/>
</td>
<td>
<input
ref="route"
disabled="true"/>
</td>
</tr>
<tr>
<td>City</td>
<td>
<input
ref="locality"
disabled="true"/>
</td>
</tr>
<tr>
<td>State</td>
<td>
<input
ref="administrative_area_level_1"
disabled="true"/>
</td>
<td>Zip code</td>
<td>
<input
ref="postal_code"
disabled="true"/>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<input
ref="country"
disabled="true"/>
</td>
</tr>
</tbody>
</table>
</div>
);
}
}
我正在尝试在 React 中重新创建这个 Google 自动完成示例:https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressform
我正在使用本教程生成正确加载 Google API 所需的高阶组件:https://www.fullstackreact.com/articles/how-to-write-a-google-maps-react-component/
自动完成功能似乎工作正常。但是,当我 select 一个建议并尝试 运行 fillInAddress()
这是我得到的错误消息:
Uncaught TypeError: Cannot read property 'getPlace' of undefined
这是我的代码 /components/GoogleApiComponent.jsx
import React from 'react';
import {GoogleApiWrapper} from 'google-maps-react';
import GoogleAutoComplete from '../components/GoogleAutoComplete';
export class Container extends React.Component {
render() {
if (!this.props.loaded) {
return <div>Loading...</div>
}
return (
<div>
<GoogleAutoComplete
/>
</div>
)
}
}
export default GoogleApiWrapper({
apiKey: 'somekey'
})(Container)
../components/GoogleAutoComplete.jsx
import React from 'react';
export default class GoogleAutoComplete extends React.Component {
static propTypes = {
}
constructor(props) {
super(props);
}
componentDidMount() {
this.initAutocomplete();
}
initAutocomplete() {
this.autocomplete = new google.maps.places.Autocomplete((this.refs.autoCompletePlaces), {types: ['geocode']});
this.autocomplete.addListener('place_changed', this.fillInAddress);
}
geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
const geolocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
});
}
}
fillInAddress() {
const componentForm = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name',
postal_code: 'short_name'
};
// Get the place details from the autocomplete object.
const place = this.autocomplete.getPlace();
for (let component in componentForm) {
this.refs.component.value = '';
this.refs.component.disabled = false;
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (let i = 0; i < place.address_components.length; i++) {
const addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
const val = place.address_components[i][componentForm[addressType]];
this.refs.addressType.value = val;
}
}
}
render() {
return (
<div>
<div>
<input
placeholder="Enter your address"
onFocus={this.geolocate}
ref="autoCompletePlaces"
/>
</div>
<table ref="address">
<tbody>
<tr>
<td>Street address</td>
<td>
<input
ref="street_number"
disabled="true"/>
</td>
<td>
<input
ref="route"
disabled="true"/>
</td>
</tr>
<tr>
<td>City</td>
<td>
<input
ref="locality"
disabled="true"/>
</td>
</tr>
<tr>
<td>State</td>
<td>
<input
ref="administrative_area_level_1"
disabled="true"/>
</td>
<td>Zip code</td>
<td>
<input
ref="postal_code"
disabled="true"/>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<input
ref="country"
disabled="true"/>
</td>
</tr>
</tbody>
</table>
</div>
);
}
}
我在 discord, and this other
这是关键线:
this.place = this.autocomplete.getPlace();
为了完整起见,我还重构了表单填写 this.place.address_components.forEach((组件, 索引) => {
const addressType = this.place.address_components[index].types[0];
if (componentForm[addressType]) {
const val = this.place.address_components[index][componentForm[addressType]];
this.refs[addressType].value = val;
}
})
完整代码如下:
import React from 'react';
export default class GoogleAutoComplete extends React.Component {
static propTypes = {
}
constructor(props) {
super(props);
this.fillInAddress = this.fillInAddress.bind(this);
}
componentDidMount() {
this.initAutocomplete();
}
initAutocomplete() {
const google = window.google;
this.autocomplete = new google.maps.places.Autocomplete((this.refs.autoCompletePlaces), {types: ['geocode']});
this.autocomplete.addListener('place_changed', this.fillInAddress);
}
geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
const geolocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
});
}
}
fillInAddress() {
const componentForm = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name',
postal_code: 'short_name'
};
// Get the place details from the autocomplete object.
this.place = this.autocomplete.getPlace();
/*this.setState({placeResult: this.place.address_components})*/
for (let component in this.componentForm) {
this.refs.component.value = '';
this.refs.component.disabled = false;
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
this.place.address_components.forEach((component, index) => {
const addressType = this.place.address_components[index].types[0];
if (componentForm[addressType]) {
const val = this.place.address_components[index][componentForm[addressType]];
this.refs[addressType].value = val;
}
})
}
render() {
return (
<div>
<div>
<input
placeholder="Enter your address"
onFocus={this.geolocate}
ref="autoCompletePlaces"
className="form-control"
type="text"
/>
</div>
<table ref="address">
<tbody>
<tr>
<td>Street address</td>
<td>
<input
ref="street_number"
disabled="true"
value=''
/>
</td>
<td>
<input
ref="route"
disabled="true"/>
</td>
</tr>
<tr>
<td>City</td>
<td>
<input
ref="locality"
disabled="true"/>
</td>
</tr>
<tr>
<td>State</td>
<td>
<input
ref="administrative_area_level_1"
disabled="true"/>
</td>
<td>Zip code</td>
<td>
<input
ref="postal_code"
disabled="true"/>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<input
ref="country"
disabled="true"/>
</td>
</tr>
</tbody>
</table>
</div>
);
}
}