React中Google PlacesService的getDetails()函数使用报错求助
修复React中Google PlacesService getDetails()的使用问题
看起来你遇到的错误是因为在React的JSX渲染流程里直接调用getDetails()导致的,还有几个小细节需要调整,我来一步步帮你解决:
问题根源
- 错误的调用时机:你在Marker的JSX内部直接执行
service.getDetails(),这会导致每次组件渲染都触发API调用,而且Google Places Service的回调会和React的状态更新不同步——当回调执行时,对应的InfoWindow DOM元素可能还没准备好,就会出现Cannot read property 'innerHTML' of undefined的错误。 - 参数重名冲突:回调函数里的第一个参数你命名为
marker,和外层循环的marker变量重名了,这会导致你在回调里访问的不是原来的标记数据,而是API返回的地点对象,容易引发逻辑混乱。 - 未绑定状态数据:InfoWindow的内容是硬编码的,没有和获取到的地点详情数据绑定,即使API调用成功,也无法展示正确信息。
修复方案
步骤1:添加状态管理地点详情和激活标记
在你的组件里添加React状态,用来存储选中地点的详情和当前激活的标记索引:
import { useState, useEffect, useRef } from 'react'; // ... const [activeKey, setActiveKey] = useState(null); const [selectedPlace, setSelectedPlace] = useState(null); const placesServiceRef = useRef(null);
步骤2:初始化PlacesService实例
在组件挂载时初始化PlacesService,避免重复创建实例:
useEffect(() => { // 创建一个隐藏的DOM元素用于初始化PlacesService(Google API要求必须绑定DOM元素) const service = new google.maps.places.PlacesService(document.createElement('div')); placesServiceRef.current = service; }, []);
步骤3:把getDetails调用移到点击事件里
创建单独的点击处理函数,在Marker被点击时再触发API请求:
const handleMarkerClick = (index, placeId) => { setActiveKey(index); setSelectedPlace(null); // 重置之前的详情数据 if (!placesServiceRef.current) return; placesServiceRef.current.getDetails({ placeId }, (place, status) => { if (status === google.maps.places.PlacesServiceStatus.OK) { setSelectedPlace(place); } }); };
步骤4:修改JSX渲染逻辑
更新Marker和InfoWindow的代码,绑定状态数据:
{markers.map((marker, i) => ( <Marker {...marker} key={i} position={marker.location} title={marker.title} place_id={marker.place_id} id={i} icon={`http://www.serwisstron.pl/icons/${marker.type}.png`} onClick={() => handleMarkerClick(i, marker.place_id)} animation={google.maps.Animation.DROP} > {i === activeKey && ( <InfoWindow onCloseClick={() => { setActiveKey(null); setSelectedPlace(null); }} > <div id="details"> <strong>{selectedPlace?.name || marker.title}</strong> <br /> <span>Address:</span> <span>{selectedPlace?.formatted_address || 'Loading address...'}</span> {/* 可以按需添加更多地点详情字段,比如电话、评分、营业时间等 */} </div> </InfoWindow> )} </Marker> ))}
关键说明
- 把API调用移到用户点击事件里,确保只有在交互时才触发请求,避免不必要的渲染和API调用浪费。
- 使用React状态管理地点详情,当数据更新时组件会自动重新渲染,InfoWindow就能展示最新的内容。
- 用
?.可选链操作符避免数据未加载时出现undefined错误,提升页面稳定性。
这样修改后,你的代码应该就能正常获取并展示地点详情了,不会再出现之前的DOM相关错误。
内容的提问来源于stack exchange,提问作者Iwona Hajczewska
相关产品推荐
相关产品推荐

