Google 放置自动完成 React 组件
Google Places Autocomplete React Component
我正在学习 React 并尝试创建一个 Google 放置自动完成组件,在 rails 应用中使用 rails gem 上的 React。这是我目前的情况,需要一些帮助来完成它。
我想我在正确加载 Google javascript 库时遇到了问题。请参阅下面来自控制台的错误消息(请注意,我的应用程序中有正确的 [KEY] 运行)。
Navigated to https://react-on-rails-basic-tutorial-mcl282.c9users.io/
js?key=[KEY]&libraries=places&callback=initAutocomplete:102 Uncaught Yc {message: "initAutocomplete is not a function", name: "InvalidValueError", stack: "Error↵ at new Yc (https://maps.googleapis.com/m…libraries=places&callback=initAutocomplete:139:73"}
Yg @ js?key=[KEY]&libraries=places&callback=initAutocomplete:102
(anonymous) @ js?key=[KEY]&libraries=places&callback=initAutocomplete:139
google.maps.Load @ js?key=[KEY]&libraries=places&callback=initAutocomplete:21
(anonymous) @ js?key=[KEY]&libraries=places&callback=initAutocomplete:138
(anonymous) @ js?key=[KEY]&libraries=places&callback=initAutocomplete:139
createReactElement.js?74ab:40 RENDERED GoogleAutoComplete to dom node with id: GoogleAutoComplete-react-component-f9a3e037-df00-4f35-9a7c-103c33b1208e with props, railsContext: Object {text: "google autocomplete"} Object {inMailer: false, i18nLocale: "en", i18nDefaultLocale: "en", href: "https://react-on-rails-basic-tutorial-mcl282.c9users.io/", location: "/"…}
clientStartup.js?0ac5:149 Uncaught TypeError: ReactOnRails encountered an error while rendering component: GoogleAutoComplete.Original message: Cannot read property 'Autocomplete' of undefined
at GoogleAutoComplete.initAutocomplete (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:3586), <anonymous>:44:48)
at GoogleAutoComplete.componentDidMount (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:3586), <anonymous>:38:12)
at eval (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2842), <anonymous>:265:25)
at measureLifeCyclePerf (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2842), <anonymous>:75:12)
at eval (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2842), <anonymous>:264:11)
at CallbackQueue.notifyAll (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2296), <anonymous>:76:22)
at ReactReconcileTransaction.close (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:3004), <anonymous>:80:26)
at ReactReconcileTransaction.closeAll (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2398), <anonymous>:206:25)
at ReactReconcileTransaction.perform (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2398), <anonymous>:153:16)
at batchedMountComponentIntoNode (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:3130), <anonymous>:126:15)
相关代码如下:
index.html.erb
<html>
<body>
<%= react_component("GoogleAutoComplete") %>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAnhYQqHo2V5AcFpcKKPX6rz0bVrw7xmZg&libraries=places&callback=initAutocomplete"
></script>
</body>
</html>
GoogleAutoComplete.jsx
import React, { PropTypes } from 'react';
export default class GoogleAutoComplete extends React.Component {
static propTypes = {
}
constructor(props) {
super(props);
this.state = {
autocomplete: {}
}
}
componentDidMount() {
this.initAutocomplete();
}
initAutocomplete() {
// eslint-disable-next-line no-undef
const autocomplete = new google.maps.places.Autocomplete((this.refs.autoCompletePlaces), {types: ['geocode']});
autocomplete.addListener('place_changed', this.fillInAddress);
this.setState({ autocomplete });
}
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 = 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 id="locationField">
<input
id="autocomplete"
placeholder="Enter your address"
onFocus={this.geolocate}
onChange={this.handleInputChange}
ref="autoCompletePlaces"
/>
</div>
<table id="address">
<tbody>
<tr>
<td>Street address</td>
<td>
<input
id="street_number"
disabled="true"/>
</td>
<td>
<input
id="route"
disabled="true"/>
</td>
</tr>
<tr>
<td>City</td>
<td>
<input
id="locality"
disabled="true"/>
</td>
</tr>
<tr>
<td>State</td>
<td>
<input
id="administrative_area_level_1"
disabled="true"/>
</td>
<td>Zip code</td>
<td>
<input
id="postal_code"
disabled="true"/>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<input
id="country"
disabled="true"/>
</td>
</tr>
</tbody>
</table>
</div>
);
}
}
错误发生是因为 initComplete()
在全局范围内不可用。 initComplete()
是 React 组件方法,不能在组件外调用。
要将 callback
参数传递给 Google 地图 API,您需要异步加载库,而不是像您那样使用 <script>
标签。
请查看以下存储库,了解它们如何处理 Google 地图库的异步加载。
我正在学习 React 并尝试创建一个 Google 放置自动完成组件,在 rails 应用中使用 rails gem 上的 React。这是我目前的情况,需要一些帮助来完成它。
我想我在正确加载 Google javascript 库时遇到了问题。请参阅下面来自控制台的错误消息(请注意,我的应用程序中有正确的 [KEY] 运行)。
Navigated to https://react-on-rails-basic-tutorial-mcl282.c9users.io/
js?key=[KEY]&libraries=places&callback=initAutocomplete:102 Uncaught Yc {message: "initAutocomplete is not a function", name: "InvalidValueError", stack: "Error↵ at new Yc (https://maps.googleapis.com/m…libraries=places&callback=initAutocomplete:139:73"}
Yg @ js?key=[KEY]&libraries=places&callback=initAutocomplete:102
(anonymous) @ js?key=[KEY]&libraries=places&callback=initAutocomplete:139
google.maps.Load @ js?key=[KEY]&libraries=places&callback=initAutocomplete:21
(anonymous) @ js?key=[KEY]&libraries=places&callback=initAutocomplete:138
(anonymous) @ js?key=[KEY]&libraries=places&callback=initAutocomplete:139
createReactElement.js?74ab:40 RENDERED GoogleAutoComplete to dom node with id: GoogleAutoComplete-react-component-f9a3e037-df00-4f35-9a7c-103c33b1208e with props, railsContext: Object {text: "google autocomplete"} Object {inMailer: false, i18nLocale: "en", i18nDefaultLocale: "en", href: "https://react-on-rails-basic-tutorial-mcl282.c9users.io/", location: "/"…}
clientStartup.js?0ac5:149 Uncaught TypeError: ReactOnRails encountered an error while rendering component: GoogleAutoComplete.Original message: Cannot read property 'Autocomplete' of undefined
at GoogleAutoComplete.initAutocomplete (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:3586), <anonymous>:44:48)
at GoogleAutoComplete.componentDidMount (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:3586), <anonymous>:38:12)
at eval (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2842), <anonymous>:265:25)
at measureLifeCyclePerf (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2842), <anonymous>:75:12)
at eval (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2842), <anonymous>:264:11)
at CallbackQueue.notifyAll (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2296), <anonymous>:76:22)
at ReactReconcileTransaction.close (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:3004), <anonymous>:80:26)
at ReactReconcileTransaction.closeAll (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2398), <anonymous>:206:25)
at ReactReconcileTransaction.perform (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:2398), <anonymous>:153:16)
at batchedMountComponentIntoNode (eval at <anonymous> (webpack-bundle.self-cdcd22e….js?body=1:3130), <anonymous>:126:15)
相关代码如下:
index.html.erb
<html>
<body>
<%= react_component("GoogleAutoComplete") %>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAnhYQqHo2V5AcFpcKKPX6rz0bVrw7xmZg&libraries=places&callback=initAutocomplete"
></script>
</body>
</html>
GoogleAutoComplete.jsx
import React, { PropTypes } from 'react';
export default class GoogleAutoComplete extends React.Component {
static propTypes = {
}
constructor(props) {
super(props);
this.state = {
autocomplete: {}
}
}
componentDidMount() {
this.initAutocomplete();
}
initAutocomplete() {
// eslint-disable-next-line no-undef
const autocomplete = new google.maps.places.Autocomplete((this.refs.autoCompletePlaces), {types: ['geocode']});
autocomplete.addListener('place_changed', this.fillInAddress);
this.setState({ autocomplete });
}
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 = 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 id="locationField">
<input
id="autocomplete"
placeholder="Enter your address"
onFocus={this.geolocate}
onChange={this.handleInputChange}
ref="autoCompletePlaces"
/>
</div>
<table id="address">
<tbody>
<tr>
<td>Street address</td>
<td>
<input
id="street_number"
disabled="true"/>
</td>
<td>
<input
id="route"
disabled="true"/>
</td>
</tr>
<tr>
<td>City</td>
<td>
<input
id="locality"
disabled="true"/>
</td>
</tr>
<tr>
<td>State</td>
<td>
<input
id="administrative_area_level_1"
disabled="true"/>
</td>
<td>Zip code</td>
<td>
<input
id="postal_code"
disabled="true"/>
</td>
</tr>
<tr>
<td>Country</td>
<td>
<input
id="country"
disabled="true"/>
</td>
</tr>
</tbody>
</table>
</div>
);
}
}
错误发生是因为 initComplete()
在全局范围内不可用。 initComplete()
是 React 组件方法,不能在组件外调用。
要将 callback
参数传递给 Google 地图 API,您需要异步加载库,而不是像您那样使用 <script>
标签。
请查看以下存储库,了解它们如何处理 Google 地图库的异步加载。