
在使用 `@react-google-maps/api` 时,`
<Circle>、<Marker>、<Polyline> 等叠加层组件依赖于底层 Google Maps JavaScript API 的 Map 实例已完全就绪。然而,<GoogleMap> 组件在首次挂载时可能存在渲染竞态(render race):其内部 map 实例尚未完成初始化,但子组件(如 <Circle>)已尝试挂载并绑定到未就绪的地图对象上,导致静默失败——无报错、无渲染,且在页面刷新后重现。
直接将 <Circle> 写在 <GoogleMap> 内部 JSX 中(如原始代码所示)是反模式,因为该写法无法确保子组件仅在 map 实例可用后才实例化。
✅ 正确做法是:利用 onLoad 回调或 useEffect + ref 显式监听地图就绪状态,并条件性渲染叠加层:
import React, { useRef, useState, useEffect } from 'react';
import { GoogleMap, LoadScript, Circle } from '@react-google-maps/api';
const EndpointMap = () => {
const mapRef = useRef<google.maps.Map | null>(null);
const [isMapLoaded, setIsMapLoaded] = useState(false);
const apiKey = 'your-api-key';
return (
<LoadScript googleMapsApiKey={apiKey} libraries={['places']}>
<div style={{ height: '100vh', width: '100vw' }}>
<GoogleMap
ref={mapRef}
mapContainerStyle={{ height: '100vh', width: '100vw' }}
center={{ lat: 49.3, lng: -123.2194 }}
zoom={8}
onLoad={(map) => {
mapRef.current = map;
setIsMapLoaded(true); // ✅ 地图加载完成,触发状态更新
}}
>
{/* ✅ 仅在地图就绪后渲染 Circle */}
{isMapLoaded && (
<Circle
center={{ lat: 49.2, lng: -123.2194 }}
radius={10000}
options={{
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.1,
}}
/>
)}
</GoogleMap>
</div>
</LoadScript>
);
};
export default EndpointMap;⚠️ 注意事项:
- 避免 setTimeout 延迟 hack:答案中建议的 500ms 延迟虽偶现有效,但不可靠(网络波动、设备性能差异会导致失效),应优先使用 onLoad 这一官方支持的生命周期回调;
- ref 与 onLoad 需配合使用:onLoad 是唯一保证 map 实例已创建并可安全操作的时机,ref 则用于后续手动调用(如 panTo、fitBounds);
- 确保 libraries 正确声明:Circle 不依赖 places 库,但若同时使用 StandaloneSearchBox,则需保留 ['places'];否则可精简为 [];
- 服务端渲染(SSR)兼容性:@react-google-maps/api 不支持 SSR,务必确保组件仅在客户端执行(如配合 dynamic + ssr: false 在 Next.js 中使用)。
总结:<Circle> 渲染失败的本质是组件挂载早于 Google Maps 实例就绪。通过 onLoad 回调驱动状态更新,并条件渲染叠加层,可 100% 解决跨设备/跨浏览器的不一致问题,这是官方推荐且生产环境验证的最佳实践。










