Next.js/React 18中Google Maps JS API无法清除旧地图状态问题
问题修复方案
问题根源
- 手动绑定地图实例导致旧路线残留:你在
DirectionsRenderer的options中手动设置了map: map,这会绕过React组件的生命周期管理,直接将路线渲染到地图上。当directionsResponse更新时,旧的渲染器实例不会被自动移除,导致新旧路线叠加。 - 未处理标记数不足的情况:当
markers长度小于2时,没有清空directionsResponse,旧的路线会一直保留。 - 标记的key使用不当:用数组索引作为
MarkerF的key,当标记顺序变化时,React无法正确识别组件的更新,导致旧标记残留。
修复后的代码
import { useState, useEffect } from "react"; import useDeepCompareEffect from "use-deep-compare-effect"; import { GoogleMap, DirectionsRenderer, MarkerF } from "@react-google-maps/api"; export function MarkerMap({ markers }) { const [map, setMap] = useState(/** @type google.maps.Map */ (null)); const [directionsResponse, setDirectionsResponse] = useState(null); const center = markers[0]; useDeepCompareEffect(() => { // 标记数不足2时清空路线响应,移除旧路线 if (!markers || markers.length < 2) { setDirectionsResponse(null); return; } async function getDirections() { const directionsService = new window.google.maps.DirectionsService(); try { const response = await directionsService.route({ origin: markers[0], destination: markers[markers.length - 1], travelMode: window.google.maps.TravelMode.DRIVING, optimizeWaypoints: false, waypoints: markers.length > 2 ? markers.slice(1, -1).map((m) => ({ location: m, stopover: true })) : [], }); setDirectionsResponse(response); } catch (err) { console.error("获取路线失败:", err); setDirectionsResponse(null); } } getDirections(); }, [markers]); return ( <GoogleMap mapContainerStyle={{ width: "100%", height: "100%" }} center={center} zoom={13} onLoad={(map) => setMap(map)} onUnmount={() => setMap(null)} > {directionsResponse && ( <DirectionsRenderer key={`route-${JSON.stringify(markers)}`} options={{ preserveViewport: true, draggable: false, hideRouteList: false, suppressMarkers: false, routeIndex: 0, polylineOptions: { strokeColor: "#FF0000", strokeWeight: 4, }, suppressBicyclingLayer: true, suppressPolylines: false, markerOptions: { label: "Sup dude", }, }} directions={directionsResponse} /> )} {!directionsResponse && markers?.map((marker) => ( <MarkerF key={`marker-${marker.lat}-${marker.lng}`} position={marker} /> ))} </GoogleMap> ); }
关键修改说明
- 移除手动地图绑定:删除
options及polylineOptions中的map: map配置,让DirectionsRenderer作为GoogleMap的子组件自动管理地图绑定,组件卸载时会自动清理旧路线。 - 处理标记数不足场景:在
useDeepCompareEffect开头判断标记数量,不足2时立即清空directionsResponse,确保旧路线被移除。 - 优化组件Key:
- 给
DirectionsRenderer添加基于markers序列化值的key,确保标记数组变化时组件重新挂载,彻底替换旧路线。 - 给
MarkerF用坐标的lat和lng组合作为key,避免索引Key导致的更新异常。
- 给
- 增加错误处理:在路线请求中加入
try/catch,防止请求失败时directionsResponse残留旧值。
内容的提问来源于stack exchange,提问作者empire29
相关产品推荐
相关产品推荐

