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

谷歌地图Marker点击无法显示Modal问题求助

问题:谷歌地图Marker点击无法触发Modal弹窗

使用google-map-react库实现带标记的谷歌地图,Marker正常渲染,但点击后Modal无法弹出。分别在MapWithPins和LocationPin组件中绑定点击事件均无效,相关代码如下:


原代码

MapWithPins.jsx

import React, {useState} from "react";
import GoogleMapReact from "google-map-react";
import LocationPin from "./LocationPin";
const MapWithPins = ({ locations, zoomLevel }) => {
  <div className="map">
    <div className="w-full h-[90vh]">
      <GoogleMapReact
        bootstrapURLKeys={{ key: process.env.REACT_APP_GOOGLE_MAPS_TOKEN }}
        defaultCenter={locations[0]}
        defaultZoom={zoomLevel}
        options={{ disableDefaultUI: true, zoomControl: true, minZoom:4, maxZoom:18 }}
   >

        { locations.map((location, index) => (
          <LocationPin
           lat={location.lat}
           lng={location.lng}
           text={location.title}
           key={index}
          />

   ))}
      </GoogleMapReact>
 </div>
</div>
);
}

LocationPin.jsx

import {Icon} from '@iconify/react';
import locationIcon from '@iconify/icons-mdi/map-marker';
import React, {useState} from 'react';

const LocationPin({text}) {
  const [showModal, setShowModal] = useState(false);

  return (
    <>
       <div className="flex items-center w-[180px] text-[#00009E]">
          <Icon icon={locationIcon} className="text-6xl" onClick={() => setShowModal(true) } />
          <p className="text-sm">{text}</p>
       </div>

       { showModal && (
            <>
               <div className="justify-center items-center flex overflow-x-hidden overflow-y-auto fixed inset-0 z-50 outline-none focus:outline-none">
              <div className="relative w-auto my-6 mx-auto max-w-3xl">
                 <div className="border-0 rounded-lg shadow-lg relative flex flex-col w-full bg-white outline-none focus:outline-none">
                  <div className="flex items-start justify-between p-5 border-b border-solid border-slate-200 rounded-t">
                    <h3 className="text-3xl font-semibold">
                      Modal Title
                    </h3>
                    <button
                      className="p-1 ml-auto bg-transparent border-0 text-black opacity-5 float-right text-3xl leading-none font-semibold outline-none focus:outline-none"
                      onClick={() => setShowModal(false)}
                    >
                      <span className="bg-transparent text-black opacity-5 h-6 w-6 text-2xl block outline-none focus:outline-none">
                        ×
                      </span>
                    </button>
                  </div>
                   <div className="relative p-6 flex-auto">
                    <p className="my-4 text-slate-500 text-lg leading-relaxed">This is some text.</p>
                  </div>
                  <div className="flex items-center justify-end p-6 border-t border-solid border-slate-200 rounded-b">
                    <button
                      className="text-red-500 background-transparent font-bold uppercase px-6 py-2 text-sm outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150"
                      type="button"
                      onClick={() => setShowModal(false)}
                    >
                      Close
                    </button>
                  </div>
                </div>
              </div>
            </div>
            </>
         )
       }
    </>

  );
}

问题排查与修复

核心问题

  1. MapWithPins语法错误:组件函数缺少return关键字,导致地图未正确渲染(虽然Marker显示,但组件逻辑存在致命问题)。
  2. 事件绑定与状态隔离:google-map-react的自定义Marker组件需要确保点击事件能穿透地图容器;同时子组件独立维护Modal状态容易出现上下文隔离问题。

修复后的代码

MapWithPins.jsx

import React, { useState } from "react";
import GoogleMapReact from "google-map-react";
import LocationPin from "./LocationPin";

const MapWithPins = ({ locations, zoomLevel }) => {
  const [selectedLocation, setSelectedLocation] = useState(null);

  return (
    <div className="map">
      <div className="w-full h-[90vh]">
        <GoogleMapReact
          bootstrapURLKeys={{ key: process.env.REACT_APP_GOOGLE_MAPS_TOKEN }}
          defaultCenter={locations[0]}
          defaultZoom={zoomLevel}
          options={{ disableDefaultUI: true, zoomControl: true, minZoom: 4, maxZoom: 18 }}
        >
          {locations.map((location, index) => (
            <LocationPin
              lat={location.lat}
              lng={location.lng}
              text={location.title}
              key={index}
              onClick={() => setSelectedLocation(location)}
            />
          ))}
        </GoogleMapReact>
      </div>

      {/* 统一在父组件管理Modal状态 */}
      {selectedLocation && (
        <>
          <div className="justify-center items-center flex overflow-x-hidden overflow-y-auto fixed inset-0 z-50 outline-none focus:outline-none bg-black/50">
            <div className="relative w-auto my-6 mx-auto max-w-3xl">
              <div className="border-0 rounded-lg shadow-lg relative flex flex-col w-full bg-white outline-none focus:outline-none">
                <div className="flex items-start justify-between p-5 border-b border-solid border-slate-200 rounded-t">
                  <h3 className="text-3xl font-semibold">
                    {selectedLocation.title}
                  </h3>
                  <button
                    className="p-1 ml-auto bg-transparent border-0 text-black opacity-5 float-right text-3xl leading-none font-semibold outline-none focus:outline-none"
                    onClick={() => setSelectedLocation(null)}
                  >
                    <span className="bg-transparent text-black opacity-5 h-6 w-6 text-2xl block outline-none focus:outline-none">
                      ×
                    </span>
                  </button>
                </div>
                <div className="relative p-6 flex-auto">
                  <p className="my-4 text-slate-500 text-lg leading-relaxed">
                    这是{selectedLocation.title}的详情内容
                  </p>
                </div>
                <div className="flex items-center justify-end p-6 border-t border-solid border-slate-200 rounded-b">
                  <button
                    className="text-red-500 background-transparent font-bold uppercase px-6 py-2 text-sm outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150"
                    type="button"
                    onClick={() => setSelectedLocation(null)}
                  >
                    Close
                  </button>
                </div>
              </div>
            </div>
          </div>
        </>
      )}
    </div>
  );
};

export default MapWithPins;

LocationPin.jsx

import { Icon } from '@iconify/react';
import locationIcon from '@iconify/icons-mdi/map-marker';
import React from 'react';

const LocationPin({ text, onClick }) => {
  return (
    <div 
      className="flex items-center w-[180px] text-[#00009E] cursor-pointer"
      onClick={onClick}
    >
      <Icon icon={locationIcon} className="text-6xl" />
      <p className="text-sm">{text}</p>
    </div>
  );
};

export default LocationPin;

关键修复说明

  • 补全MapWithPins的return关键字,确保组件正常渲染。
  • 将Modal状态提升到父组件,避免子组件状态隔离导致的弹窗无法触发问题,同时能根据选中的Marker动态展示内容。
  • 在LocationPin的外层容器绑定点击事件,确保事件能穿透地图容器被触发,替代原来仅绑定在Icon上的方式。
  • 添加Modal背景遮罩,提升交互体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 16:07:48