React+谷歌地图计算驾驶距离时useEffect状态更新报错求助
问题排查与解决方案
错误根源
- 拼写错误:代码中多处将
legs(复数)误写为leg(单数),导致尝试读取undefined的索引0,触发TypeError。 - 异步处理错误:
google.maps.DirectionsService.route默认采用回调式API,直接使用await不会等待结果返回,可能导致mapResult不是预期的路线数据。 - 缺少空值校验:未对谷歌地图返回的
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
相关产品推荐
相关产品推荐

