reactjsgoogle-mapsreact-stategoogle-directions-api

Changing google maps directions with react state


The goal is when I click the direction1 button google map renders that direction and when click the direction2 button, the map shows other direction on google map. I tried to change the state of addresses when handleClick1-2 but inside handleClick functions console.logs shows undefined on console so I think I need to do something with update state. I reduced code to be understandable, on request I can add google map functions to the question as well. I am already grateful.

My Map component

const addresses1 = [
  {
    latitude: 33.000,
    longitude: -84.000,
  },
  {
    latitude: 36.000,
    longitude: -80.000,
  }
];
const addresses2 = [
  {
    latitude: 35.000,
    longitude: -74.000,
  },
  {
    latitude: 32.000,
    longitude: -84.000,
  }
];

class Map extends Component {
  constructor(props) {
    super(props);
    this.state = {
      addresses: addresses1,
      directions: null,
      prevAddresses: null,
    };
  }
  componentDidMount() {
    this.getDirections(this.state.addresses);
  }

  handleClick1 = () => {
    this.setState({ addresses: addresses1 });
    console.log(this.addresses); // <--- shows undefined
  };
  handleClick2 = () => {
    this.setState({ addresses: addresses2 });
    console.log(this.addresses); // <--- also shows undefined
  };

  render() {
    //... makers and direction functions
    return (
      <>
          <DirectionsGoogleMap ...>
          <Button onClick={this.handleClick1} > Direction1 </Button>
          <Button onClick={this.handleClick2} > Direction2 </Button>
      </>
    );
  }
}

export default Map;


Solution

  • Are you using any google maps react libraries? In your code snippet there's a comment that console.log(this.addresses); // <--- shows undefined. You neet to call it like this console.log(this.state.addresses); to get the value of the state variable addresses.

    I can also see that you are calling <DirectionsGoogleMap ...>. How are you passing this.state.addresses in the Directions service?

    Here's a sample code and code snippet below of how I implement this using @react-google-maps/api library with inline comments:

    Index.js

    import React from "react";
    import { render } from "react-dom";
    import { LoadScript } from "@react-google-maps/api";
    import Map from "./Map";
    import "./style.css";
    
    const lib = ["places"];
    const key = ""; // PUT GMAP API KEY HERE
    class App extends React.Component {
      render() {
        return (
          <LoadScript googleMapsApiKey={key} libraries={lib}>
            <Map />
          </LoadScript>
        );
      }
    }
    
    render(<App />, document.getElementById("root"));
    
    

    Map.js

    import React, { Component } from "react";
    
    import DirectionsMap from "./DirectionsMap";
    
    let addresses1 = [
      {
        lat: 33.0,
        lng: -84.0
      },
      {
        lat: 36.0,
        lng: -80.0
      }
    ];
    let addresses2 = [
      {
        lat: 34.0,
        lng: -84.0
      },
      {
        lat: 33.0,
        lng: -84.0
      }
    ];
    
    class Map extends Component {
      constructor(props) {
        super(props);
        this.state = {
          addresses: addresses1
        };
      }
    
      handleClick1 = () => {
        this.setState({ addresses: addresses1 });
      };
      handleClick2 = () => {
        this.setState({ addresses: addresses2 });
      };
    
      render() {
        //... makers and direction functions
        return (
          <div>
            <DirectionsMap coords={this.state.addresses} />
            <button onClick={this.handleClick1}> Direction1 </button>
            <button onClick={this.handleClick2}> Direction2 </button>
          </div>
        );
      }
    }
    
    export default Map;
    

    DirectionsMap.js

    /*global google*/
    
    import React from "react";
    import { GoogleMap, DirectionsRenderer } from "@react-google-maps/api";
    
    const defaultLocation = {
      lat: 32.0,
      lng: -84.0
    };
    
    let directionsService;
    class DirectionsMap extends React.Component {
      constructor(props) {
        super(props);
      }
      state = {
        directions: null
      };
    
    //this will load the directions in map load
      onMapLoad = map => {
        directionsService = new google.maps.DirectionsService();
        this.changeDirection(this.props.coords[0], this.props.coords[1]);
      };
    
    //this will check if your props changes and render the new value of your props the props will be the parameter you passed inside <DirectionsMap /> in DirectionsMap.js
      componentDidUpdate = prevProps => {
        if (prevProps !== this.props) {
          this.changeDirection(this.props.coords[0], this.props.coords[1]);
        }
      };
    
      //function that is calling the directions service
      changeDirection = (origin, destination) => {
        directionsService.route(
          {
            origin: origin,
            destination: destination,
            travelMode: google.maps.TravelMode.DRIVING
          },
          (result, status) => {
            if (status === google.maps.DirectionsStatus.OK) {
              //changing the state of directions to the result of direction service
              this.setState({
                directions: result
              });
            } else {
              console.error(`error fetching directions ${result}`);
            }
          }
        );
      };
    
      render() {
        return (
          <div>
            <GoogleMap
              center={defaultLocation}
              zoom={5}
              onLoad={map => this.onMapLoad(map)}
              mapContainerStyle={{ height: "400px", width: "800px" }}
            >
              {this.state.directions !== null && (
                <DirectionsRenderer directions={this.state.directions} />
              )}
            </GoogleMap>
          </div>
        );
      }
    }
    
    export default DirectionsMap;