Add more than one tile layers to <Mapcontainer> in react-leaflet - reactjs

I want to add more than one tilelayers to mapcontainer. I am not able to accomplish that. I have one tilelayer like this
const magnifiedTiles = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png")
and another one here:
export default function App(): JSX.Element {
return (
<>
<MapContainer center={center} zoom={13} scrollWheelZoom={true} style={{height: 'calc(100% - 30px)'}}>
<TileLayer
attribution='© OpenStreetMap contributors'
url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
/>
</>)
}
I can either get a map reference from map container and use like magnifiedTiles.addTo(<map>)but I dont know how to get the map reference. Other option is addLayer(). However, I am not able to access it with from L.Tilelayer.
I know it leaflet it was as simple as getting map reference and using map.addLayer().

You can easily get the map reference via a ref in react-leaflet v.4.x
const [map, setMap] = useState(null)
<MapContainer
center={center}
zoom={zoom}
scrollWheelZoom={false}
ref={setMap}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</MapContainer>
and then use a useEffect to add any layer you want.
useEffect(()=> {
if (!map) return ;
map.addLayer(...);
},[])
Edit after you added the typescript tag:
Same as before only thing that changes you should install #types/react-leaflet and declare the map ref type.
import { Map as MapProp, tileLayer } from "leaflet";
...
const streets = tileLayer(
"https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}",
{
attribution:
'OpenStreetMap, CC-BY-SA, Mapbox',
maxZoom: 18,
id: "mapbox/streets-v11",
tileSize: 512,
zoomOffset: -1,
accessToken:
...
}
);
Source for streets layer that includes token
const [map, setMap] = useState<MapProp | null>(null);
...
useEffect(() => {
if (!map) return;
map.addLayer(streets);
}, [map]);
Demo

Related

React leaflet does not show anything

I tried for many hours but nothing shows up on the following code...
Does anyone know what the failure is?
// material-ui
import { TileLayer, MapContainer } from 'react-leaflet'
import 'leaflet/dist/leaflet.css';
// ==============================|| SAMPLE PAGE ||============================== //
const Dashboard_5G = () => {
return (
<MapContainer Center={[0, 0]} zoom={4} style={{height: '100%'}}>
<TileLayer
attribution='&copy OpenStreetMap contributors'
url="https://{s}.tile.osm.org/{z}/{x}/{y}.png"
/>
</MapContainer>
)
};
export default Dashboard_5G;
This is what It displays

How do you connect react-leaflet-geosearch and react-leaflet?

I've followed all documentation that is available, but it seems that I just cannot get react-leaflet-geosearch to interact and cooperate with my react-leaflet map.
This is my component rendering a <MapContainer> component:
import { MapContainer, TileLayer } from 'react-leaflet';
import LoadingScreen from '../LoadingScreen/LoadingScreen';
import './Report.css';
import { OpenStreetMapProvider, SearchControl } from "react-leaflet-geosearch";
const Report = () => {
return (
<>
<LoadingScreen />
<div className="Report">
<MapContainer center={[49.3,-123]} className="Map" zoom={10} maxZoom={19} minZoom={2}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<SearchControl
provider={new OpenStreetMapProvider()}
showMarker={true}
showPopup={false}
popupFormat={({ query, result }) => result.label}
maxMarkers={3}
retainZoomLevel={false}
animateZoom={true}
autoClose={false}
searchLabel={"Enter address, please"}
keepResult={true}
/>
</MapContainer>
</div>
</>
)
}
export default Report;
react-leaflet-geosearch seems to have recently added the <SearchControl> component to the library. It is identical to suggestions online, but I cannot get it to interact.
I occasionally receive the error:
Error: iconUrl not set in Icon options (see the docs).
Any ideas, or could this be an error because of version incompatibility/deprecated libraries?

Uncaught Error: Map container is already initialized

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>

using react-leaflet-editable with react-leaflet 2.8.0

I am integrating/including react-leaflet-editable to my existing project which relies 100% on react-leaflet v2.8.0. I am not able to upgrade at the moment as it requires too much changes to the entire project. Something we cannot afford at the moment. (Why change everything for one when one can change for all. Yes we will probably do this someday but not now)
so here is the code below. it works perfectly with react-leaflet v.3.x but the moment I siwtch to `version 2.8.0' it seizes to work.
What I have tried; Map is renamed to MapContainer in 3.x so I change that but the problem then becomes the whenCreated={setMap} parameter. I need a way to get that linked to the ReactLeafletEditable. or at least I think that is the problem.
I hope I have explained well. the code and link is below.
import React, { useRef } from "react";
import L, { Icon } from "leaflet";
import "leaflet-editable";
import ReactLeafletEditable from "react-leaflet-editable";
import {
MapContainer,
TileLayer,
LayersControl,
LayerGroup
} from "react-leaflet";
import "leaflet/dist/leaflet.css";
function Demo() {
const editRef = useRef();
const [map, setMap] = React.useState();
const editPolygon = () => {
editRef.current.startPolygon();
};
return (
<ReactLeafletEditable ref={editRef} map={map}>
<button onClick={editPolygon} className="editable-btn">
Create Polygon
</button>
<MapContainer
style={{
height: "700px",
backgroundColor: "",
flexGrow: "1",
cursor: `10`
}}
editable={true}
zoom={4}
maxZoom={18}
center={[35, 105]}
whenCreated={setMap}
>
<LayerGroup>
<TileLayer
attribution='&copy OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<TileLayer url="http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png" />
</LayerGroup>
</MapContainer>
</ReactLeafletEditable>
);
}
export default Demo;
Link to project in 3.0: https://codesandbox.io/s/react-leaflet-editable-z7tnq?file=/src/App.js
link to react-leaflet-editable : https://www.npmjs.com/package/react-leaflet-editable
PS: You can just switch the react-leaflet version on the side to 2.8.0 see the behavior.
Thank you for all support
Use a ref in combination with a useEffect to get the map instance in react-leaflet v.2.x. With that way you imitate what whenCreated does in version 3.x
const [map, setMap] = React.useState();
const mapRef = useRef();
useEffect(() => {
if (!mapRef.current) return;
setMap(mapRef.current.leafletElement);
}, []);
<ReactLeafletEditable ref={editRef} map={map}>
<button onClick={editPolygon} className="editable-btn">
Create Polygon
</button>
<Map
style={{
height: "700px",
backgroundColor: "",
flexGrow: "1",
cursor: `10`
}}
ref={mapRef}
...
Demo

ReacMapboxGl Marker doesn't show on map

import ReactMapboxGl, { Marker } from "react-mapbox-gl";
import React from "react";
const Map = ReactMapboxGl({
accessToken: process.env.REACT_APP_MAPBOX_TOKEN,
});
export default function App() {
return (
<Map
style="mapbox://styles/mapbox/streets-v9"
containerStyle={{
height: "100vh",
width: "100vw",
}}
center={[-74.006, 40.7128]}
>
<Marker coordinates={[-74.006, 40.7128]}>
<div>IAM HEEEEEEEEEEEEEEEEERE</div>
</Marker>
</Map>
);
}
This is a basic map showing using mapbox-react-gl.
There is no bug showing in console log but I can not see the marker on the map.
I think you didn't set the coordinates correctly (latitude, longitude)
They should be, based in your example [40.7128 -74.006]

Resources