Search code examples
reactjsgoogle-mapsgoogle-apireact-google-maps

How to use getDetails() in react Google Map


I am now working with Google Map in React, and now I have a problem with use function getDetails() from Google PlacesService. Here is part of my code, where I want to use this function to display info about chosen place in InfoWindow:

<Marker
  {...marker}
  key={i}
  position={marker.location}
  title={marker.title}
  place_id={marker.place_id}
  id={i}
  icon={'http://www.serwisstron.pl/icons/' + marker.type + '.png'}
  onClick={() => {
      props.toggleLocationsActive(i);
  }}
  animation={google.maps.Animation.DROP}
  >
  {i === props.activeKey && (
    service.getDetails({placeId: marker.place_id}, (marker, status) => {
      if(status === google.maps.places.PlacesServiceStatus.OK) {
      // here will be code will which put the data on InfoWindow
      }
   })
)}
   <InfoWindow onCloseClick={props.onToggleOpen}>
     <div id="details"><strong>{ marker.title } </strong><span><br/>Address:</span><span id="name"></span></div>
   </InfoWindow>)}
</Marker>

Now this code get this error:

Uncaught TypeError: Cannot read property 'innerHTML' of undefined at Object._.Tv (util.js:20) at P4.attributionText_changed (places_impl.js:32) at Lc (js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:51) at P4._.M.bindTo (js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:126) at Object.Q4.f (places_impl.js:32) at Hr. (js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:179) at js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:136 at Object. (js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:60) at js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:136 at Object. (js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:60) at js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:136 at js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:60 at js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:136 at Sd (js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:63) at Rd.wa (js?libraries=geometry,drawing,places&key=AIzaSyBqtLvddq3jzZ_Lnu9M8266EMVBfXtlUT4:136) at util.js:1

Maybe some of you know, how properly use this function in react... I was looking for this on Google long time, and I found nothing ...

Here is link to this project on Github: https://github.com/hajczek/Neighborhood---Warsaw-Cultural-Map

Thanks for any hint :)


Solution

  • All DOM modifications should be done via React since you are using it. So instead of setting innerHTML (which may lead to vulnerabilities), you should set component's state and then render markup according to the state. You could extract a component that renders InfoWindow:

    class Popup extends Component {
      state = {};
      componentDidMount() {
        const marker = this.props.marker;
    
        getInfo(marker.title).then(data => {
            console.log('---',data);
          const link = data[3][0];
          const art = data[2][0];
          if (link) {
            this.setState({
              art,
              link,
              text: "See article in Wikipedia »"
            });
          } else {
            this.setState({
              info: "Unfortunately, no info was returned for this data."
            });
          }
        });
    
        geocodeByPlaceId(marker.place_id)
          .then(results => {
            const address = results[0].formatted_address;
            this.setState({ address });
          })
          .catch(error => console.error(error));
      }
      render() {
        const props = this.props;
        return (
          <InfoWindow onCloseClick={props.onToggleOpen}>
            <div>
              <span id="title">{props.marker.title}</span>
              <br />
              <br />
              <span id="address-title">Address:</span>
              <br />
              <span>{this.state.address}</span>
              <br />
              <br />
              <span>
                <em>{this.state.art}</em>
              </span>
              <br />
              <br />
              <a target="blank" href={this.state.link}>
                {this.state.text}
              </a>
              <span>{this.state.info}</span>
            </div>
          </InfoWindow>
        );
      }
    }
    

    and render it inside of marker:

    {i === props.activeKey && (
                    <Popup marker={marker} onCloseClick={props.onToggleOpen} />
                  )}
    

    Note that getInfo should resolve promise with data:

    export const getInfo = search => {
      return fetch(
        "https://pl.wikipedia.org/w/api.php?&origin=*&action=opensearch&search=" +
          search +
          "&limit=1",
        {
          headers: { Accept: "application/json" }
        }
      )
        .then(response => response.json())
        .catch(e => requestError(e));
    

    The example above will not probably be working, it's to demo the approach.