Nextjs react-leaflet Error: Map container is already initialized - reactjs

I'm using react-leaflet in a nextjs project, after dynamically loading the map component I'm getting this error Error: Map container is already initialized. I was not getting this error in plain create-react-app project, but only when we migrated the code to nextjs.
// Location.js
import { MapContainer, TileLayer, Marker, Popup, useMap } from "react-leaflet";
function ChangeMapView({ coords, zoom }) {
const map = useMap();
map.setView(coords, zoom);
return null;
}
function Location(props) {
const position = [props.lat, props.long];
return (
<MapContainer center={position} zoom={props.placeType === "city" ? 10 : 5}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<ChangeMapView
coords={position}
zoom={props.placeType === "city" ? 10 : 5}
/>
<Marker position={position}>
<Popup>{props.city}</Popup>
</Marker>
</MapContainer>
);
}
export default Location;
Let me know if you might need more information regarding code.
const Location = dynamic(() => import("./Location"), {
ssr: false,
});
class Calculator extends React.Component {
// some code
render() {
return (
// more code
<section className="location">
<h1>Location </h1>
{this.state.selectedCity.city ? (
<Location
lat={
this.props.router.query.zip_code
? this.state.selectedCity.latitude
: this.state.selectedCity.latitude + 0.01
}
long={
this.props.router.query.zip_code
? this.state.selectedCity.longitude
: this.state.selectedCity.longitude + 0.01
}
city={
this.props.router.query.zip_code
? this.state.selectedCity.city
: this.state.stateName
}
placeType={this.props.router.query.zip_code ? "city" : "state"}
/>
) : (
""
)}
</section>
);
}
}
export default withRouter(Calculator);
(Edit): This Error doesn't come up once I downgraded to react v17. So it seems like this issue only affects react v18

Related

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 TypeError: (0 , react_geolocated__WEBPACK_IMPORTED_MODULE_7__.geolocated) is not a function

I have been seeing this error from today while finding a current location on the leaflet map. I don't know if there were a few changes with the react-geolocated new version or if I have installed the older version.
On running the app the error is
WARNING in ./src/views/Driver/DriverView.js 71:15-25
export 'geolocated' (imported as 'geolocated') was not found in'react-geolocated' (possible exports: __esModule, useGeolocated)
import Layout from "../../component/layout/Layout";
import { MapContainer,Marker,Popup, TileLayer} from 'react-leaflet';
import {geolocated} from 'react-geolocated';
import L from "leaflet";
const DEFAULT_LONGITUDE =-1.959829494;
const DEFAULT_LATITUDE = 30.126499494;
class DriverView extends React.Component{
render(){
const longitude = this.props.coords ? this.props.coords.longitude : DEFAULT_LONGITUDE;
const latitude = this.props.coords ? this.props.coords.latitude : DEFAULT_LATITUDE;
return (
<Layout>
<div>
<h3
className="font-bold underline decoration-sky-500"
data-testid="head1"
>
Simulate Bus Motion
</h3>
<div className="justify-center items-center fixed">
<div class="mapouter">
< MapContainer center ={[longitude, latitude]}
zoom={12} >
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{
!this.props.coords ?
<div className="loading">Loading</div>
:
<Marker position={[longitude, latitude]}>
<Popup>You are here</Popup>
</Marker>
}
</ MapContainer>
</div>
</div>
</div>
</Layout>
);
};
}
export default geolocated({
positionOptions: {
enableHighAccuracy: false
},
userDecisionTimeout: 5000
})(DriverView);

React leaflet map not correctly displayed even with leaflet.css import

I'm trying to create a map with reac-leaflet in ionic but I'm not displaying it correctly, also following this link: Missing Leaflet Map Tiles when using react-leaflet
WINDOW RESIZING FIX IT. What am I doing wrong on first login?
On first access this is the map:
After resizing:
Here the code.
In index.html
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css"/>
Home.tsx simplified.
import { Map, Marker, Popup, TileLayer } from 'react-leaflet';
function Home() {
return (
<IonPage>
<IonHeader>
<IonToolbar color="primary">
<IonTitle>Logged in ... </IonTitle>
</IonToolbar>
</IonHeader>
<IonContent>
<Map center={[45.24,8.55]} zoom={13}>
<TileLayer
attribution='&copy OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={[45.24,8.55]}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</Map>
</IonContent>
</IonPage>
)
}
export default Home;
In css file.
.leaflet-container {
height: 100%;
width: 100%;
}
Thank you.
I had the same problem with Ionic 5 and React Leaflet 3 and I solved like this:
In the page where you use the leaflet-react component (in your case Home), import the useIonViewDidEnter lifecycle method (see full docs) to know when the IonPage has finished animating, then trigger a window-resize event.
import { IonPage, useIonViewDidEnter, ... } from '#ionic/react';
function Home() {
/*
* trigger a 'window-resize' event when Page has finished,
* rendering and animating, so leaflet map can read a
* consistent height value
*/
useIonViewDidEnter(() => {
window.dispatchEvent(new Event('resize'));
});
return (
<IonPage>
... your Leaflet component...
</IonPage>
);
}
Is working well for me.
Let me know if it helps.
This is what I do currently and works for me:
windowDimensions.tsx
import { useState, useEffect } from 'react';
function getWindowDimensions() {
const { innerWidth: width, innerHeight: height } = window;
return {
width,
height,
};
}
export default function useWindowDimensions() {
const [windowDimensions, setWindowDimensions] = useState(
getWindowDimensions(),
);
useEffect(() => {
function handleResize() {
setWindowDimensions(getWindowDimensions());
}
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return windowDimensions;
}
app.js or componentfile.js
import useWindowDimensions from 'path/to/useWindowDimensions'; //in my case i saved it as app/utils/windowDimensions
<Map style={{height: mapHeight}} />
Note: app.js only consist of code relevant to the fix
<link href='https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.3/leaflet.css' rel='stylesheet'>
Try this

Pigeon Maps Marker Issue

I am trying to integrate a map in react specifically pigeon-maps since it is an open source.But,I am not able to get the co-ordinates from the map.Can anyone give me some code examples.I have set markers and overlay.I am able to center the map but have no idea how to get the latitude and longitude from the map.
Below is the code for the mapcomponent I am trying to create
import React, { Component } from "react";
import styles from "./mapcomponent.module.css";
import Marker from "pigeon-marker";
import Map from "pigeon-maps";
import Overlay from "pigeon-overlay";
class MapComponent extends Component {
constructor(props) {
super(props);
this.state = { lat: null, long: null };
}
componentWillMount() {
this.setState(
{
lat: Number(this.props.lat),
long: Number(this.props.long)
},
() => {
console.log("HERE", this.state.lat, this.state.long);
}
);
}
render() {
return (
<div className={styles.container} width="500px" height="500px">
<Map center={[this.state.lat, this.state.long]} zoom={12}>
<Marker anchor={[this.state.lat, this.state.long]} payload={1} />
<Overlay
anchor={[this.state.lat, this.state.long]}
offset={[120, 79]}
>
<img src="pigeon.jpg" width={240} height={158} alt="" />
</Overlay>
</Map>
</div>
);
}
}
export default MapComponent;
Can anyone help me to and extend marker and manipulate its value
We have to provide the latitude and longitude to plot the marker on map or you can get latitude and longitude from the map events (like onclick)

react-leaflet get current latlng onClick

I would be realy happy if some one could help me...
I've installed react-leaflet on my react project and the map component is loaded successfully, i need to get current latlng and show it in the Popup when i click on map but I don't know how to :(
please... please... help me...
this is my code
import React from 'react'
import { Map as LeafletMap, TileLayer, Marker, Popup } from 'react-leaflet';
class Mapp extends React.Component {
componentDidMount() {
}
render() {
return (
<LeafletMap
center={[35.755229,51.304470]}
zoom={16}
maxZoom={20}
attributionControl={true}
zoomControl={true}
doubleClickZoom={true}
scrollWheelZoom={true}
dragging={true}
animate={true}
easeLinearity={0.35}
>
<TileLayer
url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
/>
<Marker position={[35.755229,51.304470]}
draggable={true}
>
<Popup >
Popup for any custom information.
</Popup>
</Marker>
</LeafletMap>
);
}
}
export default Mapp;
Here is an example on how to display maker position in popup once map is clicked:
class MapExample extends Component {
constructor(props) {
super(props);
this.state = {
currentPos: null
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(e){
this.setState({ currentPos: e.latlng });
}
render() {
return (
<div>
<Map center={this.props.center} zoom={this.props.zoom} onClick={this.handleClick}>
<TileLayer
url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
/>
{ this.state.currentPos && <Marker position={this.state.currentPos} draggable={true}>
<Popup position={this.state.currentPos}>
Current location: <pre>{JSON.stringify(this.state.currentPos, null, 2)}</pre>
</Popup>
</Marker>}
</Map>
</div>
)
}
}
Explanation:
currentPos state is used to keep marker position
event.latLng property of Map.onClick event handler returns mouse event location
Here is a demo for your reference
What did you try to achieve that?
This will be the start:
Use the click (see https://leafletjs.com/reference-1.4.0.html#map-click) event from the LeafletMap component and call your function, like:
<LeafletMap
center={[35.755229,51.304470]}
zoom={16}
maxZoom={20}
attributionControl={true}
zoomControl={true}
doubleClickZoom={true}
scrollWheelZoom={true}
dragging={true}
animate={true}
easeLinearity={0.35}
onclick={this.handleClick}>
>
...
</LeafletMap>
In your handleClick function you get the information of lat and lng like this:
handleClick = (e) => {
const { lat, lng } = e.latlng;
console.log(lat, lng);
}
From here on, you can create your marker / popup with the information you were looking for.
Additional hint: Please make sure your code is wrapped in correctly in your post..
If you work with react-leaflet version 3.x this does not work. In this case, use the useMapEvents hook in a dummy component that you add to the map. For example, if you want to console.log the clicked position:
const LocationFinderDummy = () => {
const map = useMapEvents({
click(e) {
console.log(e.latlng);
},
});
return null;
};
Then use the LocationFinderDummy in the map as follows:
<MapContainer
center={[0, 0]}
zoom={6}>
<LocationFinderDummy />
</MapContainer>

Resources