React Leaflet地图组件窗口resize后尺寸未更新问题求助
React-Leaflet 地图窗口Resize后尺寸不更新的修复方案
问题说明
用react-leaflet制作地图时,希望地图占满header和footer之外的所有可用空间,初始加载时尺寸显示正常,但窗口调整大小后,地图尺寸并未随之更新。
问题根源
- 原代码中
useEffect的依赖数组为空,导致handleResize函数内部引用的windowHeight始终是初始状态值,无法获取最新的状态更新 - 即便容器高度更新,Leaflet地图实例不会自动检测容器尺寸变化,必须手动触发重绘逻辑
修复步骤及代码
核心改动
- 给
useEffect添加正确的依赖项,确保函数能获取最新状态 - 窗口Resize时,调用Leaflet地图的
invalidateSize()方法,强制地图重新计算容器尺寸 - 移除不必要的
loading延迟逻辑,直接计算可用高度即可
修改后的完整代码
import React, { useState, useEffect, useRef, useCallback } from "react"; import { MapContainer, TileLayer } from "react-leaflet"; import "leaflet/dist/leaflet.css"; const MyMap = () => { const mapRef = useRef(null); const [windowHeight, setWindowHeight] = useState(150); // 缓存Resize处理函数,避免重复创建 const handleResize = useCallback(() => { const header = document.querySelector("header"); const footer = document.querySelector("footer"); if (!header || !footer) return; const calculatedHeight = window.innerHeight - header.offsetHeight - footer.offsetHeight - 16; setWindowHeight(calculatedHeight); // 触发地图重绘,更新尺寸 if (mapRef.current) { mapRef.current.invalidateSize(); } }, []); useEffect(() => { // 初始加载时计算一次高度 handleResize(); window.addEventListener("resize", handleResize); // 组件卸载时移除监听 return () => window.removeEventListener("resize", handleResize); }, [handleResize]); return ( <div style={{ display: "flex", flexDirection: "column", minHeight: "100vh", margin: 0 }}> <header> <h1>HEADER</h1> </header> <main style={{ flex: "1 1 auto", padding: 0, margin: 0 }}> <MapContainer center={[51.505, -0.09]} zoom={13} style={{ height: `${windowHeight}px`, width: "100%" }} ref={mapRef} > <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' /> </MapContainer> </main> <footer> <h1>Footer</h1> </footer> </div> ); }; export default MyMap;
更简洁的CSS布局方案
可以不用JS计算高度,直接通过CSS Flexbox实现自适应布局,代码更简洁:
/* 全局样式 */ body { margin: 0; } .map-wrapper { display: flex; flex-direction: column; min-height: 100vh; } .map-wrapper main { flex: 1; } .map-container { height: 100%; width: 100%; }
对应的JSX简化版本,Resize时仅需触发地图重绘:
import React, { useRef, useEffect, useCallback } from "react"; import { MapContainer, TileLayer } from "react-leaflet"; import "leaflet/dist/leaflet.css"; const MyMap = () => { const mapRef = useRef(null); const handleResize = useCallback(() => { mapRef.current?.invalidateSize(); }, []); useEffect(() => { handleResize(); window.addEventListener("resize", handleResize); return () => window.removeEventListener("resize", handleResize); }, [handleResize]); return ( <div className="map-wrapper"> <header> <h1>HEADER</h1> </header> <main> <MapContainer center={[51.505, -0.09]} zoom={13} className="map-container" ref={mapRef} > <TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' /> </MapContainer> </main> <footer> <h1>Footer</h1> </footer> </div> ); }; export default MyMap;
内容的提问来源于stack exchange,提问作者obvdso
相关产品推荐
相关产品推荐

