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

React Leaflet地图加载时触发定位事件出现TypeError问题

问题描述

在React Leaflet中尝试在地图加载时触发定位功能,却遭遇TypeError: latlng is undefined错误。将触发逻辑改为useMapEvents的点击事件时能正常运行,但使用useMapEvents的load事件或通过useEffect实现加载时触发,均会出现相同错误。控制台能输出正确的坐标数组,但错误依然存在。

错误栈

Uncaught TypeError: latlng is undefined
    project Projection.SphericalMercator.js:24
    latLngToPoint CRS.js:28
    project Map.js:982
    latLngToLayerPoint Map.js:1004
    _project CircleMarker.js:72
    _reset Path.js:139
    onAdd Path.js:85
    _layerAdd Layer.js:114
    whenReady Map.js:1477
    addLayer Layer.js:172
    addLayer layer.js:9
    React 8
    workLoop scheduler.development.js:266
    flushWork scheduler.development.js:239
    performWorkUntilDeadline scheduler.development.js:533
...etc

组件代码

import { useState, useEffect } from "react";
import { useMap, useMapEvents, CircleMarker } from "react-leaflet";

const CurrentLocation = () => {
  const [position, setPosition] = useState(null);

  const map = useMap();

  useEffect(() => {
    map.locate().on("locationfound", (e) => {
      const pos = [e.latlng.lat, e.latlng.lng];
      console.log(pos);
      setPosition(pos);
      map.flyTo(pos, map.getZoom());
    });
  }, [map]);

  return position === null ? null : (
    <CircleMarker position={position}></CircleMarker>
  );
};

export default CurrentLocation;

主地图调用代码

...
import CurrentLocation from "../CurrentLocation/CurrentLocation";

const MainMap = (props) => {
  ...

  return (
    <div>
      <MapContainer
        style={{ height: "100vh", width: "100vw" }}
        zoom={12}
        center={centerOfMap}
      >
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        <CurrentLocation />
        ...
      </MapContainer>
    </div>
解决方案

问题根源在于两个潜在点:一是定位事件触发时地图可能未完全就绪,导致CircleMarker渲染时出现坐标解析异常;二是直接使用数组作为position属性值,可能在Leaflet内部处理时出现类型兼容问题。以下是修复后的代码:

import { useState, useEffect } from "react";
import { useMap, CircleMarker } from "react-leaflet";
import L from "leaflet";

const CurrentLocation = () => {
  const [position, setPosition] = useState(null);
  const map = useMap();

  useEffect(() => {
    // 定义定位成功后的处理函数
    const handleLocationFound = (e) => {
      // 使用Leaflet的LatLng对象创建坐标,确保类型兼容
      const pos = L.latLng(e.latlng.lat, e.latlng.lng);
      console.log(pos);
      setPosition(pos);
      map.flyTo(pos, map.getZoom());
    };

    // 等待地图完全就绪后再执行定位
    const handleMapReady = () => {
      map.locate().on("locationfound", handleLocationFound);
    };

    map.whenReady(handleMapReady);

    // 清理事件监听,避免内存泄漏
    return () => {
      map.off("locationfound", handleLocationFound);
      map.off("ready", handleMapReady);
    };
  }, [map]);

  return position ? <CircleMarker position={position} /> : null;
};

export default CurrentLocation;

关键修复点

  • 确保地图就绪后执行定位:通过map.whenReady()方法,等待地图完全初始化后再触发定位逻辑,避免在地图未就绪时添加CircleMarker。
  • 使用Leaflet原生LatLng对象:将坐标数组转换为Leaflet的LatLng对象传递给CircleMarker的position属性,避免类型解析错误。
  • 添加事件清理函数:在useEffect的返回函数中移除事件监听,防止组件卸载后仍触发事件导致内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:30:55