0

I try to display gmaps with a direction route between 2 points. So I built:

A container class:

import React, { Component } from 'react';
import { DirectionsRenderer } from 'react-google-maps';
import Map from './Map';

class MapContainer extends Component {
  constructor(props) {
    super(props);
    this.state = { directions: null };
  }
  componentWillMount() {
    const DirectionsService = new google.maps.DirectionsService();
    DirectionsService.route(
      {
        origin: new google.maps.LatLng(41.85073, -87.65126),
        destination: new google.maps.LatLng(41.85258, -87.65141),
        travelMode: google.maps.TravelMode.DRIVING
      },
      (result, status) => {
        if (status === google.maps.DirectionsStatus.OK) {
          this.setState({
            directions: result
          });
        } else {
          console.error(`error fetching directions ${result}`);
        }
      }
    );
  }
  render() {
    return (
      <Map
        googleMapURL={`https://maps.googleapis.com/maps/api/js?key=<APIKEY>&v=3.exp&libraries=geometry,drawing,places`}
        loadingElement={<div style={{ height: `100%` }} />}
        containerElement={<div style={{ height: `600px`, width: `100%` }} />}
        mapElement={<div style={{ height: `100%` }} />}
        directions={this.state.directions}
      />
    );
  }
}

export default MapContainer;

It detects the REACT lifecycle and fetches the JS code from GMaps API and then passes it down to the Map component:

import React, { Component } from 'react';
import {
  withScriptjs,
  withGoogleMap,
  GoogleMap,
  Marker,
  DirectionsRenderer
} from 'react-google-maps';
import package_ico from '../img/package.png';

const Map = withScriptjs(
  withGoogleMap(props => {
    const marker_package = (
      <Marker
        position={{
          lat: 41.85073,
          lng: -87.65126
        }}
        icon={package_ico}
      />
    );
    const marker_destination = (
      <Marker
        position={{
          lat: 41.85258,
          lng: -87.65141
        }}
      />
    );
    if (props.directions != null) {
      console.log('renderdir');
      console.log(props.directions);

      return (
        <GoogleMap defaultZoom={14} center={{ lat: 41.85073, lng: -87.65126 }}>
          {marker_package}
          {marker_destination}
          {props.directions && (
            <DirectionsRenderer directions={props.directions} />
          )}
        </GoogleMap>
      );
    } else {
      console.log('rendernodirec');
      return (
        <GoogleMap defaultZoom={14} center={{ lat: 41.85073, lng: -87.65126 }}>
          {marker_package}
          {marker_destination}
        </GoogleMap>
      );
    }
  })
);

export default Map;

The data passes correctly from the MapContainer down to the Map but then it seems like the DirectionsRenderer component that is suppose to manage the result doesn't ingest the data correctly and I get the below error message.

57 Uncaught Fc {message: "not a LatLngBounds or LatLngBoundsLiteral: unknown property f", name: "InvalidValueError", stack: "Error↵    at new Fc (https://maps.googleapis.com/m…3.exp&libraries=geometry,drawing,places:170:4324)"}
message: "not a LatLngBounds or LatLngBoundsLiteral: unknown property f"
name: "InvalidValueError"

What am I doing wrong? I tried to follow the example: https://tomchentw.github.io/react-google-maps/#directionsrenderer but I would like to avoid using recompose since I found it quite confusing...

Thanks for your feedback.

fro
  • 437
  • 4
  • 16

1 Answers1

0

I wasn't able to reproduce the same error, but it could be the sequence of loading the Google Maps script. Since you are using withScriptJs, your call to google.maps.* should be within the component that is wrapped by withScriptJs, where in your example it is outside. Try moving your componentWillMount function into the Map component as in the example below.

If this resolves the issue, it is a race condition caused by the Google Maps script not being loaded before componentWillMount is fired and google.maps.* would be unavailable.

I have a working example on CodeSandbox here. Most of the code is copied from your examples above. Just put in your API key.

import React, { Component } from "react";
import {
  withScriptjs,
  withGoogleMap,
  GoogleMap,
  Marker,
  DirectionsRenderer
} from "react-google-maps";

class Map extends React.Component {
  constructor(props) {
    super(props);
    this.state = { directions: null };
  }

  componentWillMount() {
    const DirectionsService = new google.maps.DirectionsService();
    DirectionsService.route(
      {
        origin: new google.maps.LatLng(41.85073, -87.65126),
        destination: new google.maps.LatLng(41.85258, -87.65141),
        travelMode: google.maps.TravelMode.DRIVING
      },
      (result, status) => {
        if (status === google.maps.DirectionsStatus.OK) {
          this.setState({
            directions: result
          });
        } else {
      console.error(`error fetching directions ${result}`);
        }
      }
    );
  }

  render() {
    const marker_package = (
      <Marker
        position={{
          lat: 41.85073,
          lng: -87.65126
        }}
      />
    );
    const marker_destination = (
      <Marker
        position={{
          lat: 41.85258,
          lng: -87.65141
        }}
      />
    );
    if (this.state.directions != null) {
      console.log("renderdir");
      console.log(this.state.directions);

      return (
        <GoogleMap defaultZoom={14} center={{ lat: 41.85073, lng: -87.65126 }}>
          {marker_package}
          {marker_destination}
          {this.state.directions && (
            <DirectionsRenderer directions={this.state.directions} />
          )}
        </GoogleMap>
      );
    } else {
      console.log("rendernodirec");
      return (
        <GoogleMap defaultZoom={14} center={{ lat: 41.85073, lng: -87.65126 }}>
          {marker_package}
          {marker_destination}
        </GoogleMap>
      );
    }
  }
}

export default withScriptjs(withGoogleMap(Map));
Tyler
  • 2,300
  • 1
  • 10
  • 9