React中使用Open Layer渲染地图出现重复渲染问题求助
React中OpenLayers地图重复渲染两次的解决办法
在React里用OpenLayers实现地图功能时,出现了地图重复渲染两次的情况,相关代码如下:
MapView组件代码:
export default function MapView() { const view = new View({ center: [0, 0], zoom: 2, }); useEffect(() => { new Map({ layers: [ new TileLayer({source: new OSM()}), ], view: view, target:'map', }) },[]) return ( <> <div id="map" style={{width:'100%',height:'400px'}}></div> </> ) }
父组件App代码:
function App() { return ( <div> <MapView /> </div> ); }
问题根源
- 开发环境下React的StrictMode会强制组件执行两次渲染,连
useEffect钩子也会触发两遍,这就导致OpenLayers的Map实例被创建了两次,且都挂载到同一个#map容器中,最终出现重复地图。 - 另外,
View实例是在组件函数体中创建的,每次组件渲染都会生成新的View对象,虽然不会直接引发重复渲染,但属于不必要的性能损耗。
解决办法
通过给useEffect添加清理函数、缓存View实例、用ref跟踪Map对象,确保只创建一次Map实例:
修改后的代码:
import { useEffect, useMemo, useRef } from 'react'; import { Map, View, TileLayer } from 'ol'; import OSM from 'ol/source/OSM'; export default function MapView() { // 用useMemo缓存View实例,仅初始化一次 const view = useMemo(() => new View({ center: [0, 0], zoom: 2, }), []); // 用ref存储Map实例,避免重复创建 const mapRef = useRef(null); useEffect(() => { // 仅当Map实例不存在时才创建 if (!mapRef.current) { mapRef.current = new Map({ layers: [ new TileLayer({ source: new OSM() }), ], view: view, target: 'map', }); } // 组件卸载时销毁Map实例,清理资源 return () => { if (mapRef.current) { mapRef.current.dispose(); mapRef.current = null; } }; }, [view]); return ( <div id="map" style={{ width: '100%', height: '400px' }}></div> ); }
额外优化建议
避免使用固定id作为Map的target,改用React的ref绑定DOM元素,更符合组件化思想:
// 调整后的核心代码片段 const mapContainerRef = useRef(null); useEffect(() => { if (!mapRef.current && mapContainerRef.current) { mapRef.current = new Map({ layers: [new TileLayer({ source: new OSM() })], view: view, target: mapContainerRef.current, // 使用ref指向的DOM元素 }); } return () => { if (mapRef.current) { mapRef.current.dispose(); mapRef.current = null; } }; }, [view]); return ( <div ref={mapContainerRef} style={{ width: '100%', height: '400px' }}></div> );
内容的提问来源于stack exchange,提问作者Thiluxan
相关产品推荐
相关产品推荐

