React中Mapbox Geocoder调用函数时mapMarkers State为空问题
问题:Mapbox Geocoder触发时标记数组为空导致重复标记
我有一个名为handleSearchClick()的函数,用于删除所有MapBox标记并添加新标记。通过按钮点击调用该函数时一切正常,但通过Mapbox Geocoder的on方法调用时,mapMarkers数组为空,导致功能失效,地图标记出现重复。
handleSearchClick函数
const [mapMarkers, setMarkers] = useState(stateMakrers); const handleSearchClick = () => { const sw = map.current.getBounds().getSouthWest(); const ne = map.current.getBounds().getNorthEast(); const nw = map.current.getBounds().getNorthWest(); const se = map.current.getBounds().getSouthEast(); const bounds = [{ longitude: sw.lng, latitude: sw.lat }, { longitude: nw.lng, latitude: nw.lat }, { longitude: ne.lng, latitude: ne.lat }, { longitude: se.lng, latitude: se.lat }, { longitude: sw.lng, latitude: sw.lat }]; console.log(mapMarkers); mapMarkers.forEach((marker) => marker.remove()) setMarkers([]); setList([]); getMapCourses(bounds).then((data) => { data.forEach((marker) => { setList(arr => [...arr, renderListItem(marker)]); const m = new mapboxgl.Marker() .setLngLat([marker.longitude, marker.latitude]) .setPopup( new mapboxgl.Popup({ offset: 25 }) // add popups .setHTML(`<p>${marker.name}</p>`) ) .addTo(map.current); setMarkers(ms => [...ms, m]); }); }); };
我通过setMarkers(ms => [...ms, m]);存储标记,以便函数执行时删除所有标记,通过mapMarkers.forEach((marker) => marker.remove())遍历删除标记。按钮调用该函数完全正常:
<CustomButton type="button" className="search-here-button" onClick={handleSearchClick} >Search This Area</CustomButton>
但通过geocoder.on('result', (results) =>触发时,mapMarkers状态返回空数组。我添加了useEffect监听mapMarkers变化,确认其会更新为带数据的数组,但再次触发Geocoder的result事件时数组又为空。
useEffect(() => { const geocoder = new MapboxGeocoder({ accessToken: mapboxgl.accessToken, mapboxgl, flyTo:true }); geocoder.on('result', (results) => { map.current.jumpTo({ center: results.result.center, zoom: 10 }) handleSearchClick(); console.log(mapMarkers); }) geocoderInput.current.appendChild(geocoder.onAdd(map.current)); }, [])
更新1
我尝试在函数内使用本地数组mms,mms能正常打印标记,但mapMarkers仍为空数组,怀疑是否需要在geocoder.on('result')方法内触发重新渲染?
const handleSearchClick = async () => { const sw = map.current.getBounds().getSouthWest(); const ne = map.current.getBounds().getNorthEast(); const nw = map.current.getBounds().getNorthWest(); const se = map.current.getBounds().getSouthEast(); const bounds = [{ longitude: sw.lng, latitude: sw.lat }, { longitude: nw.lng, latitude: nw.lat }, { longitude: ne.lng, latitude: ne.lat }, { longitude: se.lng, latitude: se.lat }, { longitude: sw.lng, latitude: sw.lat }]; console.log("Handle Search Click Start"); console.log(mapMarkers); // mapMarkers.forEach((marker) => marker.remove()) setMarkers([]); setList([]); const mms = []; getMapCourses(bounds).then((data) => { data.forEach((marker) => { setList(arr => [...arr, renderListItem(marker)]); const m = new mapboxgl.Marker() .setLngLat([marker.longitude, marker.latitude]) .setPopup( new mapboxgl.Popup({ offset: 25 }) // add popups .setHTML(`<p>${marker.name}</p>`) ) mms.push(m); }); }); setMarkers(mms); console.log("Markers Set local") console.log(mms) console.log("Markers Set state ") console.log(mapMarkers) };
可用但不符合最佳实践
我同时使用状态数组和本地常量数组,对两者进行添加和删除操作,但不确定这是否是规范做法。
const [mapMarkers, setMarkers] = useState(stateMakrers); const mms = []; const handleSearchClick = () => { const sw = map.current.getBounds().getSouthWest(); const ne = map.current.getBounds().getNorthEast(); const nw = map.current.getBounds().getNorthWest(); const se = map.current.getBounds().getSouthEast(); const bounds = [{ longitude: sw.lng, latitude: sw.lat }, { longitude: nw.lng, latitude: nw.lat }, { longitude: ne.lng, latitude: ne.lat }, { longitude: se.lng, latitude: se.lat }, { longitude: sw.lng, latitude: sw.lat }]; console.log("Handle Search Click Start"); console.log(mapMarkers); mms.forEach((marker) => marker.remove()) mapMarkers.forEach((marker) => marker.remove()) setMarkers([]); setList([]); while (mms.length > 0) { mms.pop(); } getMapCourses(bounds).then((data) => { data.forEach((marker) => { setList(arr => [...arr, renderListItem(marker)]); const m = new mapboxgl.Marker() .setLngLat([marker.longitude, marker.latitude]) .setPopup( new mapboxgl.Popup({ offset: 25 }) // add popups .setHTML(`<p>${marker.name}</p>`) ).addTo(map.current) mms.push(m); }); }); setMarkers(mms); };
内容的提问来源于stack exchange,提问作者Bish25
相关产品推荐
相关产品推荐

