You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 02:54:23