Uncaught Error: Map container is already initialized - reactjs

I am using React JS for making a webpage. My aim is to display a map on the front end. I am using the react-leaflet npm package for the same. However, I am getting the below error:
Error...
"Uncaught Error: Map container is already initialized.
at NewClass._initContainer (Map.js:1105:1)
at NewClass.initialize (Map.js:136:1)
at new NewClass (Class.js:22:1)
at MapContainer.js:10:1
at commitHookEffectListMount (react-dom.development.js:22969:1)
at invokePassiveEffectMountInDEV (react-dom.development.js:24948:1)
at invokeEffectsInDev (react-dom.development.js:27142:1)
at commitDoubleInvokeEffectsInDEV (react-dom.development.js:27121:1)
at flushPassiveEffectsImpl (react-dom.development.js:26865:1)
at flushPassiveEffects (react-dom.development.js:26801:1)"
Following is my code:
import React from 'react'
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
const Map = () => {
return (
<MapContainer center={[51.505, -0.09]} zoom={13}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={[51.505, -0.09]}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</MapContainer>
)
}

It seems an important question to me. Hence, answering here for sake of completeness. This is based on this link shared by #Satya S in the comments. React leaflet v3 won't work with reactJS v18 (as of the time of writing this response, things may change later. Use this link to verify), at least when using concurrent mode.
Please try version 4 alpha of React leaflet that targets version 18 of reactJS.

This works for me. Hope it could help.
import React, { useEffect } from "react";
import L from "leaflet";
import "leaflet/dist/leaflet.css";
import icon from "leaflet/dist/images/marker-icon.png";
import iconShadow from "leaflet/dist/images/marker-shadow.png";
let DefaultIcon = L.icon({
iconUrl: icon,
shadowUrl: iconShadow,
});
export default function Map() {
useEffect(() => {
var container = L.DomUtil.get("map");
if (container != null) {
container._leaflet_id = null;
}
var map = L.map("map").setView([51.505, -0.09], 13);
L.tileLayer(
"https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}",
{
attribution:
'Map data © OpenStreetMap contributors, Imagery © Mapbox',
maxZoom: 18,
id: "mapbox/streets-v11",
tileSize: 512,
zoomOffset: -1,
accessToken:
"pk.eyJ1IjoidGFyLWhlbCIsImEiOiJjbDJnYWRieGMwMTlrM2luenIzMzZwbGJ2In0.RQRMAJqClc4qoNwROT8Umg",
}
).addTo(map);
L.Marker.prototype.options.icon = DefaultIcon;
var marker = L.marker([51.5, -0.09]).addTo(map);
marker.bindPopup("<b>Hello world!</b><br>I am a popup.").openPopup();
}, []);
return <div id="map" style={{ height: "100vh" }}></div>;
}
Don't forget to insert these CSS and JS to your index.html head:
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.8.0/dist/leaflet.css" integrity="sha512-hoalWLoI8r4UszCkZ5kL8vayOGVae1oxXe/2A4AO6J9+580uKHDO3JdHb7NzwwzK5xr/Fs0W40kiNHxM9vyTtQ==" crossorigin=""/>
<script src="https://unpkg.com/leaflet#1.8.0/dist/leaflet.js" integrity="sha512-BB3hKbKWOc9Ez/TAwyWxNXeoV9c1v6FIeYiBieIWkpLjauysF18NzgR1MBNBXf8/KABdlkX68nAhlwcDFLGPCQ==" crossorigin=""></script>

Related

You may need an appropriate loader to handle this file type in react project

I have a react project. when I want to use react-leaflet I get this error:
./node_modules/react-leaflet/lib/VideoOverlay.js 10:25
Module parse failed: Unexpected token (10:25)
You may need an appropriate loader to handle this file type.
| var overlay = new LeafletVideoOverlay(url, bounds, options);
| if (options.play === true) {
> overlay.getElement()?.play();
| }
| return createElementObject(overlay, extendContext(ctx, {
I did just like document in my component. I installed with npm, and ...
note: leaflet and react-leaflet are installed. I'm using react "^18.2.0", leaflet "^1.9.2" and react leaflet "^4.1.0" in my project
project info:
My code in this component:
import React, {useEffect, useState} from "react";
import { MapContainer, TileLayer, useMap } from 'react-leaflet'
const DestinationFormAdd = (props) =>{
const position = [51.505, -0.09]
return(
<div>
<MapContainer center={position} zoom={13} scrollWheelZoom={false}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</MapContainer>
</div>
)
}

How to add a custom control (legend with buttons) to react-leaflet v.4 map?

I would like to add a custom Legend in react-leaflet v4 map, but i can't understand how to do it correctly. I have already read the https://react-leaflet.js.org/docs/example-react-control/ example but it is quite complicated.
Please check the image
to better understand the issue.
Map.js (Main map component)
import React from 'react'
import { MapContainer, TileLayer, Marker } from 'react-leaflet'
import MapLegendControl from './map/MapLegendControl'; //Custom control i want to add
function Map() {
return (
<>
<MapContainer
center={[37.983810, 23.727539]}
zoom={6}
style={{ height: '100%' }}
>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
<MapLegendControl map={map} />
</MapContainer>
</>
)
}
Custom Control (Legend)
import React from 'react'
function MapLegendControl({ map }) {
return (
<div className='leaflet-control leaflet-bar map-legend'>
<button> Test </button>
</div>
)
}
export default MapLegendControl;
Thank you in advance.

How to add wms layer on map using react leaflet

I need to highlight a layer on every states of india on map using react leaflet, So I'am adding WMS layer for that but after adding this code my map is not showing
<WMSTileLayer
layers={this.state.bluemarble ? 'nasa:bluemarble' : 'ne:ne'}
url="https://demo.boundlessgeo.com/geoserver/ows"
/>
kindly let me know what mistake am I making, and how to achieve this? I am taking reference from this example
my full code
import React from "react";
import { MapContainer, TileLayer, useMap, Marker, Popup, ZoomControl, FeatureGroup, Map, WMSTileLayer, Polygon } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import 'leaflet-draw/dist/leaflet.draw.css';
import L from 'leaflet';
import {EditControl} from 'react-leaflet-draw'
const markerIcon = new L.Icon({
iconUrl: require("../resources/placeholder.png"),
iconSize: [35, 35],
});
function Mymap(){
return(
<div className='mymap'>
<MapContainer center={[21.7679, 78.8718]} zoom={5} scrollWheelZoom={true} zoomControl={false} >
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<ZoomControl position="topright"/>
<Marker position={[21.7679, 78.8718]} icon={markerIcon}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
<WMSTileLayer
layers={this.state.bluemarble ? 'nasa:bluemarble' : 'ne:ne'}
url="https://demo.boundlessgeo.com/geoserver/ows"
/>
</MapContainer>
</div>
);
}
export default Mymap

Map markers in react-leaflet not showing image correctly

I'm confused about creating map markers in react-leaflet; some of the documentation seems to be out of date and I've seen conflicting answers on other sites.
The default <Marker> component from the official documentation's setup, with no icon property described, displays as what looks like a rectangular indent in the map. Essentially it has a shadow but no actual marker icon. If icon is set to a const importing a certain image file, the marker displays as a squashed version of that image. I experimented with setting icon to 'leaflet/dist/images/marker-icon.png' but it looks really odd as the edges are fuzzy and the icon itself looks distorted (compressed horizontally - obviously 25x55 are the dimensions I copied from elsewhere but they don't look right as default).
What's the correct way to render a normal, default, standard map marker in react-leaflet?
My code (with the squashed icon from leaflet/dist) is here:
import './App.css';
import 'leaflet/dist/leaflet.css';
import L, { divIcon } from 'leaflet';
import bear1 from './bulgaria-bear-1.jpg';
import bear2 from './bulgaria-bear-2.jpg';
import bear3 from './bulgaria-bear-3.jpg';
import markerIcon from 'leaflet/dist/images/marker-icon.png';
import React, { useState, useEffect } from 'react';
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
[...]
function PageMap(props) {
const markerIconConst = L.icon({
iconUrl: markerIcon,
iconRetinaUrl: markerIcon,
iconAnchor: [5, 55],
popupAnchor: [10, -44],
iconSize: [25, 55],
});
return (
<div classname="App">
<MapContainer id="mapid" center={[51.505, -0.09]} zoom={13} scrollWheelZoom={false}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker icon={markerIconConst} position={[51.505, -0.09]}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</MapContainer>
<p classname="App-header">
<button onClick={(() => props.navigate('Home'))}>
Home
</button>
</p>
</div>
);
As an additional question, I'm wondering why my other CSS doesn't get loaded on the map page, for example the button set as "App-header" which is meant to align with the centre. The button displays but is aligned at left. Does the MapContainer take over the whole page for its own CSS?
Your code looks correct.
The dimensions for the Leaflet marker are 24x41.
For the button style, add an uppercase "N" to className (instead of classname = "App-header").
You can find a demo here : Stackblitz
I have used in my step by step tutorial to create custom image markers using react and leaflet.
import L from 'leaflet';
export const VenueLocationIcon = L.icon({
iconUrl: require('../assets/venue_location_icon.svg'),
iconRetinaUrl: require('../assets/venue_location_icon.svg'),
iconAnchor: null,
shadowUrl: null,
shadowSize: null,
shadowAnchor: null,
iconSize: [35, 35],
className: 'leaflet-venue-icon'
});

Why I am getting 'Map' is not exported from 'react-leaflet'?

Why I am getting:
./src/components/mapComponent/MapView.jsx
Attempted import error: 'Map' is not exported from 'react-leaflet'.
I am importing this in the component:
import React, { Component } from "react";
import { Map, TileLayer } from "react-leaflet";
import "leaflet/dist/leaflet.css";
This is confusing me where to look as all looks to be correct in code....
Try with MapContainer component.
The MapContainer component is responsible for creating the Leaflet Map
instance and providing it to its child components, using a React
Context.
When creating a MapContainer element, its props are used as options to
create the Map instance.
Now you have to import MapContainer.
import { MapContainer, TileLayer, Marker } from 'react-leaflet';
<MapContainer
className="markercluster-map"
center={[51.0, 19.0]}
zoom={4}
maxZoom={18}
>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'
/>
</MapContainer>
Change Map to MapContainer.
import { MapContainer, TileLayer } from "react-leaflet";
This problem is occurring in the older version try using "react-leaflet": "^3.2.1", "leaflet": "^1.7.1", and it would resolve, if you are using react 17 and upper .
https://codesandbox.io/s/cluster-mapping-leaflet-9bkes
import { TileLayer, Tooltip, Marker, MapContainer } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import MarkerClusterGroup from "react-leaflet-markercluster";
import { customMarker } from "./constants";
import L from "leaflet";
const Cluster = () => {
let data = {
minLat: -6.1751,
maxLat: 55.7558,
minLong: 37.6173,
maxLong: 139.6917
};
const centerLat = (data.minLat + data.maxLat) / 2;
var distanceLat = data.maxLat - data.minLat;
var bufferLat = distanceLat * 0.05;
const centerLong = (data.minLong + data.maxLong) / 2;
var distanceLong = data.maxLong - data.minLong;
var bufferLong = distanceLong * 0.05;
const zoom = 4;
const cities = [
{ position: [22.583261, 88.412796], text: "A" },
{ position: [22.58289, 88.41366], text: "B" }
];
return (
<MapContainer
style={{ height: "480px", width: "100%" }}
zoom={zoom}
center={[centerLat, centerLong]}
bounds={[
[data.minLat - bufferLat, data.minLong - bufferLong],
[data.maxLat + bufferLat, data.maxLong + bufferLong]
]}
scrollWheelZoom={true}
>
<TileLayer url="http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
<MarkerClusterGroup>
{cities?.map((mark, i) => (
<Marker
style={{ color: "red" }}
key={i}
position={mark?.position}
icon={customMarker}
>
<Tooltip direction="top" offset={[10, 0]}>
<span style={{ fontSize: 14, fontWeight: "bold" }}>
{mark?.text}
</span>
</Tooltip>
</Marker>
))}
</MarkerClusterGroup>
</MapContainer>
);
};
export default Cluster;
export const customMarker = new L.Icon({
iconUrl: "https://unpkg.com/leaflet#1.5.1/dist/images/marker-icon.png",
iconSize: [25, 41],
iconAnchor: [10, 41],
popupAnchor: [2, -40]
});
You should use import {MapContainer} from "react-leaflet" instead of Map and before doing that install both react-leaflet and leaflet by
$ npm i leaflet react-leaflet
Hope this solve your problem
This problem is occurring in the newer version try using "react-leaflet": "^2.8.0","leaflet": "^1.7.1"and it would resolve

Resources