Search code examples
javascriptreact-leaflet

React-leaflet Uncaught TypeError: Cannot read properties of undefined (reading 'marker')


I'm using react-leaflet and I have created a map in which I have already put markers. And I'm just trying to make a function that when the button is clicked, adds a new marker. But I'm getting this error: Uncaught TypeError: Cannot read properties of undefined (reading 'marker')

Note: The filterGare1 part and the gare variables correspond to longitude and latitude data retrieved from a JSON file

Here my code:

import "./App.css";
import "leaflet/dist/leaflet.css";
import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
import { iconPerso } from "./iconMarker";
import { map, 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"
);



function getLayers(){
  var newMarker = new L.marker([42.5020902, 2.1131379])
  .addTo(map)
  .bindPopup("MARKER TEST");

}

export default function App() {
  const [, updateState] = React.useState();
  const forceUpdate = React.useCallback(() => updateState({}), []);

  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#-0.2/0.00000/76.51878"
        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>'
      />

      {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={getLayers}>get Layers</button>
          </Popup>
        </Marker>
      ))}

      <GetZoom />
    </MapContainer>
  );
}

I searched for an answer online but none of the proposed solutions solved my problem. Some talk about markerCluster -> Leaflet 1.7: L.MarkerClusterGroup is not a function But that doesn't really correspond to what I'm trying to do. I only want to add one marker to my map but I dont't know where my mistake could be, can anyone see it? Thanks in advance


Solution

  • It might be the import of L, this is how I am able to use L

    import L, { LeafletMouseEventHandlerFn } from "leaflet";
    

    However you mix leaflet and react-leaflet workflows for marker. I would advise you to just use the react-leaflet tag for all your markers.

    Simply add the marker to a state on click and render that state the same way you do with your other markers

    export default function App() {
      const [, updateState] = React.useState();
      const forceUpdate = React.useCallback(() => updateState({}), []);
    
      const [markers, setMarkers] = React.useState([]);
      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#-0.2/0.00000/76.51878"
            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>'
          />
    
          {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={() => setMarkers([[42.5020902, 2.1131379]])}>
                  get Layers
                </button>
              </Popup>
            </Marker>
          ))}
          {markers.map((marker, i) => (
            <Marker key={`marker-${i}`} position={marker} />
          ))}
    
          <GetZoom />
        </MapContainer>
      );
    }
    

    Edit: The setMarkers did just add the position and not the position in an array. Which should have resulted in marker just being a number and not a position. My example is changed to setMarkers([[42.5020902, 2.1131379]].

    You could of course use your own object as the the items in the array, this was just to show with the least needed data (position)