reactjsleafletreact-leaflet

Leaflet marker rendering but showing the "broken image" placeholder


Here is what it looks like:

1

My code:

Map.js

//the next 3 lines changes nothing kept it in bc I found this online as a potential solution
//and didn't want to get this suggested
import L from 'leaflet';
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.imagePath = "/";

function Map() {

 let position = [x, y];

 return (
   <div>
     <div id="mapid">
       <MapContainer className="leaflet" center={position} zoom={13} scrollWheelZoom={true}>
         <TileLayer
           attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
           url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
         />
          <Marker position={position}>
            <Popup>
              A pretty CSS3 popup. <br /> Easily customizable.
            </Popup>
          </Marker>
        </MapContainer>
      </div>
    </div>

  );
};

index.css

.leaflet {
  height: 500px;
  width: 100%;
}

#mapid {
  height: 500px;
  margin-top: 50px;
  margin-bottom: 150px;
}

img.leaflet-marker-icon {
   background-image: 
   url('<url>');
}

I do not really understand how the marker is rendering and not rendering at the same time, it does not make sense.

Obviously, I am trying to render something that is causing some image to not render but I do not see which it would be.

The code is pretty much straight up from the example code: https://leafletjs.com/examples/quick-start/. Which is why I am confused.

I have included the style and script tags in index.html already.


Solution

  • If you pay really close attention, you actually have 2 broken image placeholders shown in your screenshot:

    leaflet marker icon shadow image

    The root cause is that your build engine (most likely webpack, since you use React) rewrites the URL's in Leaflet CSS file, which interferes with how Leaflet uses it to detect the path to its images.

    See Leaflet/Leaflet#4968 and PaulLeCam/react-leaflet#453 for more details.

    As for workarounds, you have 2 possible easy options:

    import 'leaflet/dist/leaflet.css';
    import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css'; // Re-uses images from ~leaflet package
    import * as L from 'leaflet';
    import 'leaflet-defaulticon-compatibility';
    
    import 'leaflet/dist/leaflet.css';
    import * as L from 'leaflet';
    delete L.Icon.Default.prototype._getIconUrl;
    
    L.Icon.Default.mergeOptions({
      iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
      iconUrl: require('leaflet/dist/images/marker-icon.png'),
      shadowUrl: require('leaflet/dist/images/marker-shadow.png'),
    });