0

Я пытаюсь воссоздать этот Google автозаполнения пример в реакции: https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressformфункция getPlace не работает с Google автозаполнения в реакции

Я использую этот учебник для создания более высокого порядка компонент, необходимый для правильной загрузки API Google: https://www.fullstackreact.com/articles/how-to-write-a-google-maps-react-component/

Функциональность автозаполнения работает нормально. Однако, когда я выбираю предложение и попытаться запустить 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>  
    ); 
    } 
} 

ответ

1

Я понял это, с некоторой помощью людей старше на discord, и этот другой stackoverflow question. В соответствии с этим ответом ключевым моментом является «Внутри place_changed-callback ключевое слово this указывает на объект, который был вызван событием». Я сделал это, и это сработало.
Это ключевая строка: 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() { 
     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>  
    ); 
    } 
} 
Смежные вопросы