最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React Locate on map - Stack Overflow

programmeradmin5浏览0评论

I would like to add the module "React-leaflet-locate-control" on Map. Unfortunately, I have this error "TypeError: Cannot read property 'addLayer' of undefined" and I don't know how to correct this error.

Can you help me please ?

Here is my ponent Map :

import './Map.css';
import React, { Component } from 'react';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import L from "leaflet";
import { getLat, getLng } from '../../Store.js';
import SearchBar from '../SearchBar/SearchBar.js';
import LocateControl from 'react-leaflet-locate-control';

const customMarker = new L.icon({
    iconUrl: "/[email protected]/dist/images/marker-icon.png",
    iconSize: [25, 41],
    iconAnchor: [13, 0]
});

export default class MapLeaflet extends Component {

    constructor(props) {
        super(props);
        this.state = {
            lat: getLat(),
            lng: getLng(),
        }
    }

    updateMarker = (e) => {
        this.props.updateMarkerPosition(e.latlng.lat, e.latlng.lng);
        this.setState({
            lat: e.latlng.lat,
            lng: e.latlng.lng
        })
    }

    render() {
        const position = [this.state.lat, this.state.lng]
        const locateOptions = {
            position: 'topright',
            strings: {
                title: 'Show me where I am, yo!'
            },
            onActivate: () => {} // callback before engine starts retrieving locations
        }
        return (
            <div className="map">
                <Map center={position} zoom={13} className="map" onClick={this.updateMarker}>
                    <TileLayer
                        attribution='&amp;copy <a href="">OpenStreetMap</a> contributors'
                        url="https://{s}.tile.openstreetmap/{z}/{x}/{y}.png"
                    />
                    <Marker position={position} icon={customMarker}>
                        <Popup>
                            A pretty CSS3 popup. <br /> Easily customizable.
                        </Popup>
                    </Marker>
                    <SearchBar />
                    <LocateControl options={locateOptions} startDirectly/>
                </Map>
            </div>
        )
    }
}

I would like to add the module "React-leaflet-locate-control" on Map. Unfortunately, I have this error "TypeError: Cannot read property 'addLayer' of undefined" and I don't know how to correct this error.

Can you help me please ?

Here is my ponent Map :

import './Map.css';
import React, { Component } from 'react';
import { Map, TileLayer, Marker, Popup } from 'react-leaflet';
import L from "leaflet";
import { getLat, getLng } from '../../Store.js';
import SearchBar from '../SearchBar/SearchBar.js';
import LocateControl from 'react-leaflet-locate-control';

const customMarker = new L.icon({
    iconUrl: "https://unpkg./[email protected]/dist/images/marker-icon.png",
    iconSize: [25, 41],
    iconAnchor: [13, 0]
});

export default class MapLeaflet extends Component {

    constructor(props) {
        super(props);
        this.state = {
            lat: getLat(),
            lng: getLng(),
        }
    }

    updateMarker = (e) => {
        this.props.updateMarkerPosition(e.latlng.lat, e.latlng.lng);
        this.setState({
            lat: e.latlng.lat,
            lng: e.latlng.lng
        })
    }

    render() {
        const position = [this.state.lat, this.state.lng]
        const locateOptions = {
            position: 'topright',
            strings: {
                title: 'Show me where I am, yo!'
            },
            onActivate: () => {} // callback before engine starts retrieving locations
        }
        return (
            <div className="map">
                <Map center={position} zoom={13} className="map" onClick={this.updateMarker}>
                    <TileLayer
                        attribution='&amp;copy <a href="http://osm/copyright">OpenStreetMap</a> contributors'
                        url="https://{s}.tile.openstreetmap/{z}/{x}/{y}.png"
                    />
                    <Marker position={position} icon={customMarker}>
                        <Popup>
                            A pretty CSS3 popup. <br /> Easily customizable.
                        </Popup>
                    </Marker>
                    <SearchBar />
                    <LocateControl options={locateOptions} startDirectly/>
                </Map>
            </div>
        )
    }
}
Share Improve this question edited Jan 9, 2019 at 2:27 Mohamed Ibrahim Elsayed 2,9643 gold badges26 silver badges46 bronze badges asked Jan 8, 2019 at 21:21 KloniKloni 1512 silver badges11 bronze badges 1
  • This github issue seems related to your problem : github./PaulLeCam/react-leaflet/issues/… – Treycos Commented Jan 8, 2019 at 21:27
Add a ment  | 

3 Answers 3

Reset to default 14

react-leaflet-locate-control package is not patible with the latest version (v2) of react-leaflet and in fact the similar issue has been reported here

Since react-leaflet-locate-control represents a wrapper for leaflet-locatecontrol plugin, the following custom ponent for react-leaflet could be utilized instead which offers the same functionality as react-leaflet-locate-control:

import React, { Component } from "react";
import { withLeaflet } from "react-leaflet";
import Locate from "leaflet.locatecontrol";

class LocateControl extends Component {
  ponentDidMount() {
    const { options, startDirectly } = this.props;
    const { map } = this.props.leaflet;

    const lc = new Locate(options);
    lc.addTo(map);

    if (startDirectly) {
      // request location update and set location
      lc.start();
    }
  }

  render() {
    return null;
  }
}

export default withLeaflet(LocateControl);

Installation

1) install a plugin: npm install leaflet.locatecontrol

2) include the following CSS resources into public/index.html:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn./font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr/npm/leaflet.locatecontrol/dist/L.Control.Locate.min.css">

Here is a demo (source code)

You actually do not need any external module to get the current location in react or any other JavaScript libraries

you can use

if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(position => //Do something with it  );
  }

Here is a react way :

 const [currentLocation, setCurrentLocation] = React.useState([0, 0]);
//change [0,0] to something that makes sense to your users in case they deny access to location.  


    useEffect(() => {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(
                position => 
                        setCurrentLocation([position.coords.latitude, position.coords.longitude]))
        }
    }, []);


    return (
        <Map center={currentLocation} zoom={15}>
          // the rest ie . TileLayer,Marker,Popup 
        </Map>

If you are using Typescript like me. I made it work with v2 using below ponent code

import L from 'leaflet';
import { withLeaflet, MapControl, MapControlProps } from 'react-leaflet';
import Locate from 'leaflet.locatecontrol';
import './Geolocate.css';

type GeolocateProps = L.Control.LocateOptions & MapControlProps;

class Geolocate extends MapControl<GeolocateProps> {
  createLeafletElement(props: GeolocateProps) {
    const { leaflet, ...options } = props;
    const locate = Locate as any;
    const lc = new locate(options);
    return lc;
  }
}
export default withLeaflet(Geolocate);

Additionally, you can skip including Font awesome and library's own css files and provide your own styles instead

Geolocate.css

.leaflet-control-locate a.leaflet-bar-part div {
  background-image: url(../../images/geolocation.png);
  background-size: 22px 74px;
  background-position: top 2px left 2px;
  background-repeat: no-repeat;
  width: 30px;
  height: 30px;
}

.leaflet-control-locate a.leaflet-bar-part div.loading {
  background-position: top -24px left 2px;
}

.leaflet-control-locate.active a.leaflet-bar-part div.locate {
  background-position: top -50px left 2px;
}

@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
  .leaflet-control-locate a.leaflet-bar-part div {
    background-image: url(../../images/geolocation-2x.png);
  }
}

Of course you will have to install leaflet.locatecontrol using npm first

npm i leaflet.locatecontrol

Hope this helps.

发布评论

评论列表(0)

  1. 暂无评论