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

点击Google地图自带地标后自定义Marker的InfoWindow无法显示

解决Google地图点击原生地标后自定义Marker的InfoWindow无法显示问题

问题

从事件数据库生成自定义Marker,点击时会显示包含事件名称与描述的InfoWindow,但点击Google地图自带的地标(如埃菲尔铁塔这类POI)后,再点击自定义Marker,InfoWindow就不再显示,添加clickable属性也无改善。

原因

  1. 点击原生POI时,Google地图会自动弹出原生InfoWindow,干扰React组件的状态逻辑,导致后续自定义Marker的点击无法正确触发InfoWindow渲染。
  2. 原代码中hasData的设置时机错误,异步数据还未加载完成就标记为有数据,可能引发Marker或InfoWindow的渲染异常。
  3. 未处理地图点击事件,无法在点击原生POI或空白区域时重置选中状态,导致状态残留。

修复后的代码

import React, { useEffect, useState } from 'react';
import { GoogleMap, LoadScript, Marker, InfoWindow } from '@react-google-maps/api';
import { getlocArray, retrieveListings } from './listings';

const containerStyle = {
  width: '600px',
  height: '600px',
};

const center = {
  lat: 34.0703,
  lng: -118.448,
};

function MapsComponent() {
  const [markers, setMarkers] = useState([]);
  const [selectedMarker, setSelectedMarker] = useState(null);
  const [listings, setListings] = useState([]);
  const [hasData, setHasData] = useState(false);

  useEffect(() => {
    async function fetchData() {
      try {
        const data = await retrieveListings();
        setListings(data);
        const importedlocArray = await getlocArray();
        
        if (importedlocArray.length > 0) {
          setMarkers(
            importedlocArray.map((location, index) => ({
              key: index,
              position: {
                lat: location[1],
                lng: location[0],
              },
            }))
          );
        }
        // 数据加载完成后再标记为有数据
        setHasData(true);
      } catch (err) {
        console.error('加载数据失败:', err);
        setHasData(true); // 即使加载失败也显示状态,可根据需求调整
      }
    }

    fetchData();
  }, []);

  const handleMarkerClick = (marker) => {
    setSelectedMarker(marker);
  };

  const handleInfoWindowClose = () => {
    setSelectedMarker(null);
  };

  // 点击地图(包括原生POI)时重置选中状态
  const handleMapClick = () => {
    setSelectedMarker(null);
  };

  return (
    <>
      {hasData ? (
        <LoadScript googleMapsApiKey="API-key">
          <GoogleMap 
            mapContainerStyle={containerStyle} 
            center={center} 
            zoom={15}
            onClick={handleMapClick} // 添加地图点击事件
          >
            {markers.map((marker) => (
              <Marker
                key={marker.key}
                position={marker.position}
                onClick={() => handleMarkerClick(marker)}
              />
            ))}
            {selectedMarker && (
              <InfoWindow
                position={selectedMarker.position}
                onCloseClick={handleInfoWindowClose}
              >
                <div>
                  <h3>{listings[selectedMarker.key]?.title || '无标题'}</h3>
                  <p>{listings[selectedMarker.key]?.description || '无描述'}</p>
                </div>
              </InfoWindow>
            )}
          </GoogleMap>
        </LoadScript>
      ) : (
        <p>加载事件中...</p>
      )}
    </>
  );
}

export default React.memo(MapsComponent);

关键修改点

  • 将setHasData(true)移到异步数据加载完成后,确保地图渲染时数据已准备就绪。
  • 给GoogleMap添加onClick事件,点击地图任意区域(包括原生POI)时重置selectedMarker,清除状态残留。
  • 在InfoWindow的内容中添加可选链操作符?.,避免因数据索引异常导致的渲染错误。
  • 移除了不必要的sleep函数,异步数据加载无需手动延迟。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 15:50:18