You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+谷歌地图计算驾驶距离时useEffect状态更新报错求助

问题排查与解决方案

错误根源

  1. 拼写错误:代码中多处将legs(复数)误写为leg(单数),导致尝试读取undefined的索引0,触发TypeError。
  2. 异步处理错误:google.maps.DirectionsService.route默认采用回调式API,直接使用await不会等待结果返回,可能导致mapResult不是预期的路线数据。
  3. 缺少空值校验:未对谷歌地图返回的routes和legs数组进行空值判断,若地址解析失败或无可用路线时,直接取索引0会报错。

修复步骤

1. 修正拼写错误

将所有result.routes[0].leg[0]替换为result.routes[0].legs[0]。

2. 正确处理DirectionsService的异步逻辑

将calculateRoute中的异步调用改为Promise封装(或直接使用回调),确保获取到有效的路线数据后再更新状态。

3. 增加空值安全校验

在useEffect中先判断routes和legs数组是否存在且有内容,再读取数据。

完整修改后的代码

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;
    }

    const directionsService = new google.maps.DirectionsService();
    try {
      // 封装为Promise处理异步
      const mapResult = await new Promise((resolve, reject) => {
        directionsService.route({
          origin: originRef.current.value,
          destination: destinationRef.current.value,
          travelMode: google.maps.TravelMode.DRIVING,
        }, (response, status) => {
          if (status === google.maps.DirectionsStatus.OK) {
            resolve(response);
          } else {
            reject(new Error(`路线请求失败: ${status}`));
          }
        });
      });
      setResult(mapResult);
    } catch (err) {
      console.error(err);
      // 可添加用户可见的错误提示,比如alert或页面状态提示
    }
  };

  useEffect(() => {
    console.log("I'm being triggered");
    // 增加空值安全校验
    if (result?.routes?.length > 0 && result.routes[0].legs?.length > 0) {
      const leg = result.routes[0].legs[0];
      setDistanceText(leg.distance.text);
      setDurationText(leg.duration.text);
      setDistanceCalc(leg.distance.value);
      setDurationCalc(leg.duration.value);
    } else {
      console.error("路线数据不完整或无效");
      // 可选:重置相关状态
      // setDistanceText(undefined);
      // setDurationText(undefined);
    }
  }, [result]);

  useEffect(() => {
    console.log("Distance Text: ", distanceText);
    console.log("Duration Text: ", durationText);
    console.log("Distance Calc: ", distanceCalc);
    console.log("Duration 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>
    </>
  );
}

额外建议

  • 可以添加用户友好的错误提示,比如当路线请求失败时,在页面上显示错误信息而不仅仅是控制台输出。
  • 可以对输入框的地址进行预校验,确保用户输入的是有效的地址格式。

内容的提问来源于stack exchange,提问作者Coolkid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 14:44:55