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

React Leaflet地图组件窗口resize后尺寸未更新问题求助

React-Leaflet 地图窗口Resize后尺寸不更新的修复方案

问题说明

用react-leaflet制作地图时,希望地图占满header和footer之外的所有可用空间,初始加载时尺寸显示正常,但窗口调整大小后,地图尺寸并未随之更新。

问题根源

  1. 原代码中useEffect的依赖数组为空,导致handleResize函数内部引用的windowHeight始终是初始状态值,无法获取最新的状态更新
  2. 即便容器高度更新,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='&copy; <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='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
          />
        </MapContainer>
      </main>
      <footer>
        <h1>Footer</h1>
      </footer>
    </div>
  );
};

export default MyMap;

内容的提问来源于stack exchange,提问作者obvdso

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 12:14:51