I have an issue, I seem not to find how to give a ref to every popup in react class component. Here's my code:
export default class LiveTracking extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
popup: React.createRef()
};
render() {
return (
<MapContainer center={[-12.576, 140.664]} zoom={5}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
{this.state.data.map((item) => (
<Marker>
<Popup ref={this.state.popup}>
<div className="popup">
<p>This is the popup</p>
</div>
</Popup>
</Marker>
))}
</MapContainer>
);
}
}
I need to give every popup a ref so I know what popup that shows and I have to close it after a click event. Or if you know how to close all popups after clicking on react-leaflet let me know. Looking forward to your help, Regards
Related
I have an array of videos which are displayed by Bootstrap carousel embedded in a modal dialog box. The video doesn't start playing automatically when the modal is show but you need to click on it and it will start playing. My issues is that on slide change the current video playing won't pause. So this is what i need to achieve, to pause current video when the user changes slides(back or forth). How can I do this?
BTW I am using React Js.
Any help is greatly valued.Thanks.✌️
Below is my Video Carousel component.
import React, { Component } from "react";
import 'bootstrap/dist/css/bootstrap.min.css';
import Carousel from 'react-bootstrap/Carousel';
import "../carousel.css";
export default class VideoCarousel extends Component {
constructor(props) {
super(props);
this.videoRef = React.createRef();
// this.state = {
// index: 0,
// isPlaying: false
// }
}
render(){
return(
<div>
<Carousel activeIndex={this.index} onSelect={this.handleChange} interval={null} className="carousel">
{this.props.items.map((item, index) => {
return (
<Carousel.Item key={index}>
<video
ref = {this.videoRef}
className="videoItem"
controls="controls"
>
<source src={item.src} type="video/mp4"/>
</video>
<Carousel.Caption>
{/* <h2>{item.title}</h2> */}
</Carousel.Caption>
</Carousel.Item>
);
})}
</Carousel>
</div>
)
}
}
Problem
You are using the same reference for all the items. After running the map function this.videoRef will be equal to the last element of the array.
Solution 1: keep the references in an array
Create the ref initialized by an empty array:
this.videoRef = React.createRef([]);
Iterate over the elements and assign the reference based on the index value:
<Carousel activeIndex={this.index} onSelect={this.handleChange} interval={null} className="carousel">
{this.props.items.map((item, index) => {
return (
<Carousel.Item key={index}>
<video
ref = {el => this.videoRef.current[index] = el}
...
>
...
</Carousel.Item>)
})}
</Carousel>
To pause the video use the element reference at specific position:
this.videoRef.current[index].pause();
Solution 2: Create a component for the carrousel item
You can handle the controls functions on componentDidMount/componentWillUnmount
this.videoRef = React.createRef(null);
Assign the reference:
export default class VideoCarouselItem extends Component {
constructor(props) {
super(props);
this.videoRef = React.createRef();
}
render(){
<Carousel.Item key={this.props.key}>
<video
ref = {this.videoRef}
...
>
</Carousel.Item>
}
}
Then through properties pass the info you need.
Trying to add a button that when pressed it moves the map to new York city. But whenever I try and use the button I get the error:
Error: Invalid hook call. Hooks can only be called inside of the body
of a function component. This could happen for one of the following
reasons
I understand that I need to put the hook of flyto into a function as it's a hook but how would you do that combined with a class component.
Code:
export default class App extends React.Component {
constructor() {
super();
this.onClickNewYork = this.onClickNewYork.bind(this)
}
onClickNewYork() {
const { map } = useLeaflet();
map.flyTo([40.730610, -73.935242], 15)
}
return (
<>
<Button onPress={this.onClickNewYork}>
<Map center={position} zoom={0}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
</map>
</>
)
}
You cannot do it like this in react-leaflet version 2.x. Moreover you cannot use hooks inside class based components.
Normally to take the map reference you would use withLeaflet HOC but this is available only in components placed as Map child components.
What you should do here instead is take a map reference using a ref and then use it to call map.fly()
mapRef = React.createRef();
onClickNewYork() {
this.mapRef.current.leafletElement.flyTo([40.73061, -73.935242], 15);
}
<Map
center={position}
zoom={0}
style={{ height: "90vh" }}
ref={this.mapRef}
>
...
Demo
This is my Dashnoard.js file, i dont have an html file .My question is how to add the drawing toolbar on the leaflet map.At the moment i have the map only...
Thank you!
import React from 'react'
import { Map, Marker, Popup, TileLayer } from 'react-leaflet'
import { compose } from 'redux'
import "leaflet/dist/leaflet.css";
import L from 'leaflet';
export class Dashboard extends React.Component{
constructor() {
super();
this.state = {
lat: 42.696295,
lng: 23.303643,
zoom: 10,
};
}
render() {
const position = [this.state.lat, this.state.lng]
return(
<div className='dashboard container'>
<Map id="map" style={{ height: "50vh" }} center={position} zoom={13}>
<TileLayer
attribution='© OpenStreetMap contributors'
url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
/>
<Marker position={position}>
<Popup>
A pretty CSS3 popup. <br /> Easily customizable.
</Popup>
</Marker>
</Map>
</div>
)
} }
export default compose()(Dashboard);
I have successfully initialize the map on the page,but at the next step i cannto initialize na drawing comonent and set to the map.
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>
I keep getting null return from this component. What am I Missing???
import React from 'react';
import Lightbox from 'react-images';
const IMAGES = [
{ src: "https://c2.staticflickr.com/9/8817/28973449265_07e3aa5d2e_b.jpg" },
{ src: "https://c2.staticflickr.com/9/8356/28897120681_3b2c0f43e0_b.jpg" },
{ src: "https://c4.staticflickr.com/9/8887/28897124891_98c4fdd82b_b.jpg" }
];
class ImagesRow extends React.Component {
constructor(props){
super(props);
this.onClose = this.onClose.bind(this);
this.gotoNext = this.gotoNext.bind(this);
this.gotoPrevious = this.gotoPrevious.bind(this);
}
onClose(){
}
gotoNext(){
}
gotoPrevious(){
}
render(){
return (
<Lightbox
images={IMAGES}
onClose={this.onClose}
onClickPrev={this.gotoPrevious}
onClickNext={this.gotoNext}
/>
);
}
}
This results in an empty div. Is there a required prop I'm missing?
http://jossmac.github.io/react-images/#getting-started
It is not obvious from the documentation, but react-images will not render a grid/or a gallery of your images. It will only render the Lightbox component once a image is clicked.
So, in order to get what you want (which is a gallery of some kind, AND the light box component applied to images of that gallery, then you need more than just 'react-images'. You can render the images on their own, or with another gallery/grid npm library.
For example you can render an array of images with just the normal <img> tag. BUT, be sure that each image has the "onClick" set to be a function that opens the Lightbox. see below:
...
<Grid imagesArray={thumbs} onClick={this.openLightbox.bind(this)} columns={3} padding={3} />
<Lightbox
images={images}
isOpen={this.state.lightboxIsOpen}
onClickPrev={this.gotoPrevious}
onClickNext={this.gotoNext}
onClose={this.closeLightbox}
currentImage={this.state.currentImage}
/>
I believe you need isOpen. Try
return (
<Lightbox
isOpen
images={IMAGES}
onClose={this.onClose}
onClickPrev={this.gotoPrevious}
onClickNext={this.gotoNext}
/>
);