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

React-Leaflet添加Marker报错:Cannot read properties of undefined (reading 'marker')

错误原因分析

出现Uncaught TypeError: Cannot read properties of undefined (reading 'marker')的核心原因有两个:

  1. Leaflet导入错误:你通过import { map, L} from "leaflet";解构导入L,但Leaflet的L是默认导出,不是命名导出,因此这里的L变量实际是undefined,调用L.marker自然会报错。
  2. 违背React-Leaflet的声明式范式:直接调用Leaflet原生API操作地图实例(addTo(map))是错误的——你导入的map是Leaflet创建地图的函数,而非当前MapContainer生成的地图实例,同时React-Leaflet要求通过状态管理组件渲染,而非直接操作DOM层的地图对象。
解决方案

步骤1:修正Leaflet导入

将Leaflet的导入语句改为默认导入:

import L from "leaflet";
// 移除原来的import { map, L} from "leaflet";

步骤2:用React状态管理自定义Marker

在App组件中添加状态变量,用于存储新增的Marker数据:

const [customMarkers, setCustomMarkers] = React.useState([]);

步骤3:修改新增Marker的函数

把原getLayers改为更新状态的函数,向customMarkers数组中添加新的Marker坐标和弹窗内容:

const addCustomMarker = () => {
  const newMarker = {
    position: [42.5020902, 2.1131379],
    popupText: "MARKER TEST"
  };
  setCustomMarkers(prev => [...prev, newMarker]);
};

步骤4:渲染新增的Marker

在MapContainer中添加代码,渲染customMarkers中的所有Marker:

{customMarkers.map((marker, index) => (
  <Marker
    key={index} // 简单用index做key,实际项目建议用唯一标识
    position={marker.position}
    icon={iconPerso}
  >
    <Popup>{marker.popupText}</Popup>
  </Marker>
))}

完整修正后的代码

import "./App.css";
import "leaflet/dist/leaflet.css";
import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
import { iconPerso } from "./iconMarker";
import L from "leaflet";
import dataGares from "./data/referentiel-gares-voyageurs.json";

const center = [46.227638, 2.213749];

const filterGare1 = dataGares.filter(
  (gare) => gare.fields.segmentdrg_libelle === "a"
);

export default function App() {
  const [customMarkers, setCustomMarkers] = React.useState([]);

  const addCustomMarker = () => {
    const newMarker = {
      position: [42.5020902, 2.1131379],
      popupText: "MARKER TEST"
    };
    setCustomMarkers(prev => [...prev, newMarker]);
  };

  let niveau = filterGare1;

  return (
    <MapContainer
      center={center}
      zoom={6}
      style={{ width: "100vw", height: "100vh" }}
    >
      <TileLayer
        url="https://api.maptiler.com/maps/basic/256/{z}/{x}/{y}.png?key=F4ZxF5g8ioWE3GlTx3i0"
        attribution='<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>'
      />

      {/* 原有从JSON加载的Marker */}
      {niveau.map((gare) => (
        <Marker
          key={gare.recordid}
          position={[
            gare.fields.latitude_entreeprincipale_wgs84,
            gare.fields.longitude_entreeprincipale_wgs84,
          ]}
          icon={iconPerso}
        >
          <Popup>
            <h3> {"Name : " + gare.fields.gare_alias_libelle_noncontraint} </h3>
            <button onClick={addCustomMarker}>Add Marker</button>
          </Popup>
        </Marker>
      ))}

      {/* 新增的自定义Marker */}
      {customMarkers.map((marker, index) => (
        <Marker
          key={index}
          position={marker.position}
          icon={iconPerso}
        >
          <Popup>{marker.popupText}</Popup>
        </Marker>
      ))}

      <GetZoom />
    </MapContainer>
  );
}

额外说明

  • 移除了原代码中无用的forceUpdate相关代码,因为状态更新会自动触发组件重新渲染。
  • 修正了TileLayer的URL,移除了末尾的无效参数,避免影响地图加载。
  • 如果需要多次添加不同坐标的Marker,可以修改addCustomMarker函数,接收坐标参数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 22:05:59