React+Google Maps点击Marker仅显示单个信息窗口问题排查
问题分析与解决方案
嘿,这问题我一眼就看出来啦!你现在遇到的核心问题是所有Marker共享了同一个isOpen状态,导致只要这个状态切换,所有绑定它的InfoWindow都会一起弹出或关闭。
为什么会这样?
你的withStateHandlers里只维护了一个全局的布尔值isOpen,所有Marker的InfoWindow都依赖这个值做显示判断。不管你点击哪个Marker,触发的都是同一个onToggleOpen函数,切换的是全局的isOpen——那自然所有窗口都会跟着一起变化啦!
两种解决办法,任你选:
方法一:用状态记录当前打开的Marker标识
我们把单个布尔值换成存储“当前打开的Marker的唯一标识”(比如索引、item的ID),这样就能精准控制单个窗口的显示:
- 修改状态管理部分:
const MapWithAMakredInfoWindow = compose( // 把isOpen换成openMarkerId,初始值为null(表示没有窗口打开) withStateHandlers(() => ({ openMarkerId: null }), { onToggleOpen: ({ openMarkerId }) => (markerId) => ({ // 如果点击的是已经打开的Marker,就关闭;否则打开它 openMarkerId: openMarkerId === markerId ? null : markerId }) }), withScriptjs, withGoogleMap )(props => <GoogleMap defaultZoom={8} defaultCenter={{ lat: 44.8350088, lng: -0.5872689999999999 }} > {this.state.PartenaireData.map(function (item, i) { if (item.coordinates.latitude && item.coordinates.longitude) return ( <Marker position={{ lat: item.coordinates.latitude, lng: item.coordinates.longitude }} // 点击时传递当前Marker的索引(或者item.id,如果有唯一ID的话更稳妥) onClick={() => props.onToggleOpen(i)} key={i} > // 只有当openMarkerId等于当前索引时,才显示InfoWindow {props.openMarkerId === i && <InfoWindow onCloseClick={() => props.onToggleOpen(i)}> <div> <div>{item.titre}</div> <div>autre data</div> </div> </InfoWindow>} </Marker>) })} </GoogleMap>);
方法二:封装独立的Marker组件(更简洁)
把每个Marker和对应的InfoWindow封装成单独的组件,让每个组件自己维护isOpen状态,彻底避免全局状态冲突:
- 创建独立组件:
// 单独的Marker组件,自己管理状态 const MarkerWithInfoWindow = ({ item }) => { const [isOpen, setIsOpen] = useState(false); const toggleOpen = () => { setIsOpen(!isOpen); }; return ( <Marker position={{ lat: item.coordinates.latitude, lng: item.coordinates.longitude }} onClick={toggleOpen} > {isOpen && <InfoWindow onCloseClick={toggleOpen}> <div> <div>{item.titre}</div> <div>autre data</div> </div> </InfoWindow>} </Marker> ); };
- 在地图组件中使用:
const MapWithAMakredInfoWindow = compose( withScriptjs, withGoogleMap )(props => <GoogleMap defaultZoom={8} defaultCenter={{ lat: 44.8350088, lng: -0.5872689999999999 }} > {this.state.PartenaireData.map(function (item, i) { if (item.coordinates.latitude && item.coordinates.longitude) // 直接用封装好的组件,每个组件独立管理状态 return <MarkerWithInfoWindow item={item} key={i} /> })} </GoogleMap>);
两种方法的小提示:
- 方法一适合需要在父组件控制窗口状态的场景(比如手动关闭所有窗口);
- 方法二更简洁,组件职责更清晰,适合大多数普通场景。
内容的提问来源于stack exchange,提问作者tetar
相关产品推荐
相关产品推荐

