React + Firestore 9开发中Google Maps标记无法渲染问题求助
问题根源
你遇到的问题来自三个核心错误:
fetchMarkers异步处理逻辑错误:getDocs是异步Promise方法,你当前的代码会在Promise回调执行前就返回空的markerData数组,无法拿到后端返回的实际数据- 未使用React状态管理标记数据:普通JS变量的修改不会触发React组件重渲染,因此即使后续
arrayData被赋值,地图组件也不会重新渲染标记节点 - 数据请求位置错误:直接在组件顶层调用请求方法,会导致组件每次重渲染都重复触发请求,产生额外性能开销
修正后代码
import { useState, useEffect } from 'react' import { getDocs, query, collection } from 'firebase/firestore' import { LoadScript, GoogleMap, Marker } from '@react-google-maps/api' // 此处补充你自己定义的db、apiKey、containerStyle、center等变量 // 修正异步请求逻辑,直接返回处理后的标记数组Promise function fetchMarkers(){ return getDocs(query(collection(db, "places"))) .then((snapshot) => { const markerData = [] snapshot.forEach((doc) => { markerData.push({...doc.data(), id: doc.id}) // 补充文档id作为渲染key,避免告警 }) return markerData }) } export default function Map() { // 用state存储标记数据,修改state会触发组件重渲染 const [markerList, setMarkerList] = useState([]) // 可选加载状态,优化用户体验 const [loading, setLoading] = useState(true) // 把请求放在useEffect中,组件挂载时仅执行一次 useEffect(() => { const getMarkers = async () => { const data = await fetchMarkers() setMarkerList(data) setLoading(false) } getMarkers() }, []) if(loading) return <div>地图加载中...</div> return ( <div id="map"> <LoadScript googleMapsApiKey={apiKey}> <GoogleMap mapContainerStyle={containerStyle} center={center} zoom={13} options={{ fullscreenControl: false, mapTypeControl: false, streetViewControl: false, styles: [{ elementType: "labels", featureType: "poi", stylers: [{ visibility: "off" }] }] }} > {markerList.map((marker) => ( <Marker key={marker.id} position={{ lat: marker.latitud, lng: marker.longitud }} /> ))} </GoogleMap> </LoadScript> </div> ) }
改动说明
- 调整
fetchMarkers返回值为完整的Promise实例,异步处理完成后返回实际的标记数据数组 - 使用React内置的
useStateHook存储标记列表,更新状态会自动触发组件重渲染,地图上的标记会同步更新 - 使用
useEffectHook包裹请求逻辑,只在组件首次挂载时执行一次数据拉取,避免重复请求 - 手动补充文档id到标记数据中,解决列表渲染的key属性告警问题
内容的提问来源于stack exchange,提问作者Pedro Montesinos Navarro
相关产品推荐
相关产品推荐

