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

Next.js/React 18中Google Maps JS API无法清除旧地图状态问题

问题修复方案

问题根源

  1. 手动绑定地图实例导致旧路线残留:你在DirectionsRenderer的options中手动设置了map: map,这会绕过React组件的生命周期管理,直接将路线渲染到地图上。当directionsResponse更新时,旧的渲染器实例不会被自动移除,导致新旧路线叠加。
  2. 未处理标记数不足的情况:当markers长度小于2时,没有清空directionsResponse,旧的路线会一直保留。
  3. 标记的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 05:22:25