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

react-leaflet使用useRef调用flyTo时返回undefined如何解决

问题原因

你的代码中MapContainer被包裹在width && height的条件渲染逻辑中,只有当useResizeDetector获取到外层容器的宽高后,地图组件才会完成挂载,whenCreated回调才会触发给mapRef.current赋值。而你当前把触发按钮放在了条件渲染分支外,地图未挂载时按钮就可以被点击,此时mapRef.current自然是undefined。

解决方案

  • 将按钮移动到条件渲染的代码块内,保证只有地图加载完成后按钮才会展示,避免用户提前点击
  • 给外层容器设置最小高度,避免useResizeDetector无法正常获取宽高导致地图始终不渲染
  • 可增加加载状态提示,优化宽高未获取到时的用户体验

修改后的核心代码示例

import React, { VFC, useRef } from "react"
import { useResizeDetector } from 'react-resize-detector';
import { MapContainer, TileLayer, CircleMarker, Popup } from 'react-leaflet'
import { MapDatum } from "./types"
import L from 'leaflet'
import { Button } from "@material-ui/core";

type MapProps = {
  mapData: MapDatum[]
}

export const MapContent: VFC<MapProps> = ({ mapData }) => {
  const { ref, width, height } = useResizeDetector()
  // 初始化ref时明确指定类型和初始值
  const mapRef = useRef<L.Map | null>(null)
  const disneyLandLatLng = {lat:33.8121, lng:-117.9190}

  function handleOnFlyTo() {
    // 兜底判断避免报错
    if (!mapRef.current) return
    mapRef.current.flyTo(disneyLandLatLng, 14, {
      duration: 2
    });
  }

  return (
    // 增加最小高度保证resize detector能正常获取尺寸
    <div ref={ref} style={{ width: "100%", height: "100%", minHeight: "500px" }}>
      {width && height ? (
        <>
          <Button onClick={handleOnFlyTo}>Fly</Button>
          <MapContainer
            style={{ width: "100%", height: "100%" }}
            bounds={[[-180, -270], [180, 270]]}
            center={[0, 0]}
            zoom={1}
            scrollWheelZoom={true}
            attributionControl={false}
            whenCreated={ mapInstance => { mapRef.current = mapInstance }}
          >
            <TileLayer
              attribution=""
              url="https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png"
            />
            {mapData.map(({ label, lon, lat, r, color }, i) => (
              <CircleMarker
                key={i}
                center={[lat, lon]}
                radius={r}
                fillColor={color}
                stroke={false}
                fillOpacity={.6} >
                <Popup>
                  {label}
                </Popup>
              </CircleMarker>
            ))}
          </MapContainer>
        </>
      ) : (
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
          地图加载中...
        </div>
      )}
    </div>
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 01:24:04