getPlace函数无法与Google自动完成功能配合使用

时间:2017-02-23 03:02:32

标签: javascript google-maps reactjs google-maps-api-3 react-on-rails

我正在尝试重新制作此Google自动填充示例:cssmin

我正在使用本教程生成正确加载Google API所需的高阶组件:https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressform

自动完成功能似乎工作得很好。但是,当我选择一个建议并尝试运行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)

../组件/ 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>      
    );
  }
}

1 个答案:

答案 0 :(得分:1)

我在discord和其他人stackoverflow question的帮助下找到了这一点。根据该答案,关键点是“在place_changed-callback内部,关键字指向已触发事件的对象。”。我做了那个改变而且工作正常。
这是关键路线: this.place = this.autocomplete.getPlace();

为了完整性,我还重新考虑了表格填写 this.place.address_components.forEach((component,index)=&gt; {

 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() {
      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>      
    );
  }
}