skip to Main Content

i’m building a webapp using React and Google maps. I want to calculate distance between 2 places using driving. I’m getting an error when updating state, i’m not sure what’s wrong.

Uncaught TypeError: Cannot read properties of undefined (reading ‘0’)

I’ve indicated the error line in the code.
I know that setState is asynchronous and useEffect normally helps with this.
I tried placing that setState in its own useEffect but that still gave an error.

import React, { useState, useRef, useEffect } from "react";
import {
  useJsApiLoader,
  Autocomplete,
} from "@react-google-maps/api";

const center = { lat: 48.8584, lng: 2.2945 };

export default function Test() {
  const [map, setMap] = useState(/** @type google.maps.Map */ (null));
  const [directionsResponse, setDirectionsResponse] = useState(null);
  const [distanceText, setDistanceText] = useState();
  const [durationText, setDurationText] = useState();
  const [distanceCalc, setDistanceCalc] = useState();
  const [durationCalc, setDurationCalc] = useState();
  const [result, setResult] = useState();

  const { isLoaded } = useJsApiLoader({
    id: "google-map-script",
    googleMapsApiKey: process.env.REACT_APP_GOOGLEMAPS_KEY,
    libraries: ["maps", "places"],
  });

  /** @type React.MutableRefObject<HTMLInputElement> */
  const originRef = useRef();
  /** @type React.MutableRefObject<HTMLInputElement> */
  const destinationRef = useRef();

  const calculateRoute = async () => {
    console.log("Clicked");

    if (originRef.current.value === "" || destinationRef.current.value === "") {
      return;
    }

    // eslint-disable-next-line no-undef
    const directionsService = new google.maps.DirectionsService();
    const mapResult = await directionsService.route({
      origin: originRef.current.value,
      destination: destinationRef.current.value,
      // eslint-disable-next-line no-undef
      travelMode: google.maps.TravelMode.DRIVING,
    });

    setResult(mapResult);

    console.log("Result2: ", result);
  };

  useEffect(() => {
    console.log("I'm being triggered");
    if (result) {
      setDistanceText(result.routes[0].legs[0].distance.text); //error line
      setDurationText(result.routes[0].leg[0].duration.text);  //error line
      setDistanceCalc(result.routes[0].leg[0].distance.value); //error line
      setDurationCalc(result.routes[0].leg[0].duration.value); //error line
    }
  }, [result]);

  useEffect(() => {
    console.log("Distance Text: ", distanceText);
    console.log("Duration Text: ", durationText);
    console.log("Distance Calc: ", distanceCalc);
    console.log("Distance Calc: ", durationCalc);
  }, [distanceText, durationText, durationCalc, distanceCalc]);

  return (
    <>
      <Autocomplete>
        <input type="text" placeholder="Origin" ref={originRef} />
      </Autocomplete>
      <Autocomplete>
        <input type="text" placeholder="Destination" ref={destinationRef} />
      </Autocomplete>
      <button onClick={() => calculateRoute()}>Calculate</button>
    </>
  );
}

Any assistance would be appreciated.

2

Answers


  1. useEffect(() => {
        console.log("I'm being triggered");
    
        if (result) {
          setDistanceText(result.routes[0].legs[0].distance.text); //error line
          setDurationText(result.routes[0].legs[0].duration.text);  //error line
          setDistanceCalc(result.routes[0].legs[0].distance.value); //error line
          setDurationCalc(result.routes[0].legs[0].duration.value); //error line
        }
      }, [result]);
    

    There are typos in your code where you are using leg instead of legs. Update your useEffect code with above code.

    enter image description here

    enter image description here

    Login or Signup to reply.
  2. Try this in your code :

      useEffect(() => {
              console.log("I'm being triggered");
              if (result) {
                const route = result.routes[0];
                if (route && route.legs && route.legs[0]) {
                  const leg = route.legs[0];
                  if (leg.distance && leg.duration) {
                    setDistanceText(leg.distance.text);
                    setDurationText(leg.duration.text);
                    setDistanceCalc(leg.distance.value);
                    setDurationCalc(leg.duration.value);
                  }
                }
              }
            }, [result]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search