React Leaflet Map not displaying - react-leaflet

I have the basic example from React-leaflet, but for the life of me I cannot get anything to display. I am using this fix from Jeremy Monson for the common babel-loader issue. I was having the same problems of no display when I went through the manual fixes. Right now I am using styled-components, but I was having the same issue with regular CSS. My map component page looks like this.
import React from 'react'
import styled from '#emotion/styled'
import { MapContainer, TileLayer, Marker, Popup } from '#monsonjeremy/react-leaflet'
const Leaflet = styled.div`
height:500px;
width:500px;
`
const Map = () => {
return (
<Leaflet>
<MapContainer center={[51.505, -0.09]} zoom={13} scrollWheelZoom={false}>
<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>
</Leaflet>
)
}
export default Map
I am loading the leaflet css in the of head my index.html page. I am importing my map component in App.js and rendering it there.
Any thoughts or pointing in the right direction would be much appreciated.

Add height to your map container using style prop:
<MapContainer
center={[51.505, -0.09]}
zoom={13}
scrollWheelZoom={false}
style={{height: '100%'}} // Add a height
>
...

Related

Material popover does not close upon onClose call

Have this Chat component and inside an input have an en endorsement, inside that i want to have a popover to show and pick emojis, The pop over pops up but the closing functionality does not work.
import React from "react";
import "./styles.css";
import Chat from "./Chat";
export default function App() {
return (
<div className="App">
<Chat />
</div>
);
}
Here is a sandbox example of that.
https://codesandbox.io/embed/zealous-maxwell-3115b?fontsize=14&hidenavigation=1&theme=dark
<InputAdornment position="end">
<IconButton aria-describedby={id} onClick={handleEmojiClick}>
<EmojiEmotionsIcon />
</IconButton>
<PopOver
open={open}
id={id}
anchorEl={anchorEl}
setAnchorEl={setAnchorEl}
/>
<IconButton>
<SendIcon />
</IconButton>
</InputAdornment>
Just puted the Popover out of IconButton Component and it is working now.

Classnames mismatch using Material-UI and NextJS

Using Intersection Observer API I'm trying to render a Material-UI Component by visibility on the viewport.
export default function Index() {
const [onScreen, theRef] = useOnScreen({
rootMargin: "-300px",
ssr: true
});
const classes = useStyles();
return (
<Container maxWidth="sm">
<DummyContainer />
<div
ref={theRef}
style={{
height: "100vh",
padding: "20px",
backgroundColor: "green",
transition: "all .5s ease-in"
}}
>
{onScreen && (
<Box className={classes.rootBox} my={16}>
<Typography variant="h2" gutterBottom>
Content Lazy using Intersection Observer
</Typography>
<Copyright />
</Box>
)}
</div>
<Box className={classes.rootBox} my={4}>
<Typography variant="h2" gutterBottom>
Content no lazy, why this Box loses margin?
</Typography>
<Typography gutterBottom>
If you request this page with JavaScript disabled, you will notice
that has been properly rendered in SSR
</Typography>
</Box>
</Container>
);
}
Basic stuff, onScreen is a toggled boolean using Intersection Observer
In order to be "SEO friendly" I'm using NextJS and I wanted this component to always be visible in SSR and conditional visible in CSR.
The problem arises during rehydration in CSR, it's seems that some classnames after the lazy component are recreated and I'm losing styling in second Box component.
I've created this CodeSandbox to have a look : https://codesandbox.io/s/nextjsmaterialuiclassnamemismatch-1j4oi
Is this a bug in MaterialUI, JSS? Or most probably I'm doing something wrong?

How to insert a Link into a GridListTile in Gatsby

I am trying to have a clickable grid of images within Gatsby using the Material-UI GridList
Inside the GridListTile I am not able to put a Gatsby Link around my image or inside the GridListTileBar.
export default function SingleLineGridList() {
const classes = useStyles();
return (
<div className={classes.root}>
<GridList className={classes.gridList} cols={1.5} cellHeight="300">
{tileData.map(tile => (
<GridListTile key={tile.img} className={classes.gridListTile}>
<Link to={`product/1`}>
<img src={tile.img} alt={tile.title} />
</Link>
<GridListTileBar
title={tile.title}
classes={{
root: classes.titleBar,
title: classes.title,
}}
/>
</GridListTile>
))}
</GridList>
</div>
);
}
I get the error 'TypeError: Cannot read property 'muiName' of undefined'
I have found similar examples from straight react so presume it is something to do with the Gatsby link component
I realise it is likely to have something to do with component wrapping but have no idea how to implement this.
How can I make the Gatsby Link element an accepted element with the GridListTile?

Customizing react-leaflet marker icons by using font awesome

It is more theoretical question, rather than a problem.
How to use font awesome icons as react-leaflet map marker icons?
I would like to have such an icon selector control to assign(customize) each marker icon I have got on my map. By the way I am using JSX components of Map and Marker.
Is it possible to achieve this?
Anybody have a sample pen about this? I have really googled it strongly but couldn't find any plugin but a fontawesome plugin that is working only with Leaflet 1.0.
So any idea appreciated.
Thanks in advance.
For some reasons code is not getting formatted. See code on code sandbox
Here is how you can use font-awesome icons as markers.
Add font-awesome CDN to your index.html
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU"
crossorigin="anonymous">
Use divIcon along with renderToStaticMarkup from react-dom/server to generate icon for marker. And pass this divIcon to Marker as a icon prop.
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { renderToStaticMarkup } from 'react-dom/server';
import { divIcon } from 'leaflet';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import './styles.css';
class App extends Component {
state = {
lat: 51.505,
lng: -0.091,
zoom: 13,
};
render() {
const position = [this.state.lat, this.state.lng];
const iconMarkup = renderToStaticMarkup(<i className=" fa fa-map-marker-alt fa-3x" />);
const customMarkerIcon = divIcon({
html: iconMarkup,
});
return (
<Map center={position} zoom={this.state.zoom}>
<TileLayer
attribution="&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
url="https://{s}.tile.osm.org/{z}/{x}/{y}.png"
/>
<Marker position={position} icon={customMarkerIcon}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</Map>
);
}
}
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
Override divIcon default style by adding the following class to your css file
.leaflet-div-icon {
background: transparent;
border: none;
}
Here is a working example of the same:
https://codesandbox.io/s/4ry180jl34
For those who already use the React components of Fontawesome (FontAwesomeIcon), there is a solution that does not require importing via CDN again. It uses the same principles of Murli's answers, but instead of adding <i className=" fa fa-map-marker-alt fa-3x" />, you can convert the FontAwesomeIcon component to html and pass that into the html attribute of the divIcon. It would look like this (adapted the example of the accepted answer):
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import ReactDOMServer from 'react-dom/server';
import Leaflet from 'leaflet'
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import './styles.css';
// FontAwesome requirements
import { faUserAstronaut } from '#fortawesome/free-solid-svg-icons'
library.add(faUserAstronaut)
class App extends Component {
state = {
lat: 51.505,
lng: -0.091,
zoom: 13,
};
render() {
const position = [this.state.lat, this.state.lng];
const iconHTML = ReactDOMServer.renderToString(<FontAwesomeIcon icon='user-astronaut' />)
const customMarkerIcon = new Leaflet.DivIcon({
html: iconHTML,
});
return (
<Map center={position} zoom={this.state.zoom}>
<TileLayer
attribution="&copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
url="https://{s}.tile.osm.org/{z}/{x}/{y}.png"
/>
<Marker position={position} icon={customMarkerIcon}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</Map>
);
}
}
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
Create divIcon and insert it into icon property:
// marker-icons.js
import L from 'leaflet';
const factory = new L.divIcon({
className: '',
iconAnchor: [12, 25],
labelAnchor: [-6, 0],
popupAnchor: [0, -15],
iconSize: [25, 41],
html: `<span class="fa fa-industry"></span>`
});
export default { factory };
Use icon in component file:
// component.js
import { factory } from './marker-icons';
<MapContainer center={[12.23432, 87.234]} zoom={6} scrollWheelZoom={false}>
<TileLayer attribution='© OpenStreetMap contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
<Marker position={45.4534, 23.43]} icon={factory}>
<Popup>Help text</Popup>
</Marker>
</MapContainer>

Error while loading a basic react-leaflet map

I am new to react-leaflet.
I'm working on a Flask React project and I'm trying to load a react-leaflet map.
I'm getting the below error :
Uncaught TypeError: Cannot use 'in' operator to search for 'default' in undefined
at react-leaflet.js:7
at React__default (react-leaflet.js:4)
at react-leaflet.js:5
Versions :
react-leaflet : v1.9.1
leaflet.css : v1.3.1
react-leaflet.js : v1.9.1
I have added the necessary routes for rendering the Appbody.
But I'm unable to figure out what is wrong.
import React, {Component} from 'react'
import {Map, Marker, Popup, TileLayer} from 'react-leaflet'
const position = [51.505, -0.09]
class MainMap extends Component {
render() {
return (
<div>
<Map center={position} zoom={13}>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution="© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors"
/>
<Marker position={position}>
<Popup>
<span>A pretty CSS3 popup.<br/>Easily customizable.</span>
</Popup>
</Marker>
</Map>
</div>
);
}
}
export default MainMap;
import React, {Component} from 'react';
import MainMap from "./map";
class AppBody extends Component {
render() {
return (
<div>
<MainMap/>
</div>
);
}
}
export default AppBody;
.leaflet-container {
position: absolute;
height: 100%;
width: 100%;
}
I'm currently using react-leaflet and I never had this kind of error, but I can see something wrong in the code (I don't know if those resolve the problem).
Firstly have you imported the leaflet.css file? You need to import this in the index.js or in the current file
import "leaflet/dist/leaflet.css";
You have also to add a ref props in the map component like this
<Map ref = "map" {...otherprops} >
I think the only problem in your code is surrounding the Map element by div tags.
So if you remove them and make the Map element at the top, then the problem should be solved.
TL;DR
Do not include the react-leaflet CDN in your index.html if you have installed it with npm or yarn.
Well, after much probing around with the problem myself I think you may have set up things incorrectly in the <head> of your index.html, this is how I had it set up before with the error happening:
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin=""/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-leaflet/2.0.0/react-leaflet.js"></script>
and solving the issue:
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css"
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
crossorigin=""/>
Notice the difference? If you have installed react-leaflet with npm or yarn, you'll see that you don't need to add the leaflet script in your <head>. What was happening before is that the react-leaflet script was loading before the webpacked js files and it therefore could not find React. The react-leaflet source code that threw the error looked like this:
var React__default = 'default' in React ? React['default'] : React;
And obviously, if there was no React object in the first place, there will be an error when trying to find the 'default' key.
Hope this helps someone some day!