Why aren't React-leaflet & Leaflet working in combination?

Viewed 167

I have a Webstrom React Project and a leaflet Map const Map is not defined as class it's defined as const Map = () => {

I get a response from a URL with axios. I want do set LatLong from the JSON.stringify(res.data, null, 2) response

I have imported L from "leaflet", and "react-leaflet" has the classes of {Map, TilesLayer, Marker, Popup}.

I need to get the response into the map

Here is my example:

VisonMap.js

import React from "react";
import axios from "axios";
import {MapContainer, TileLayer, Marker, Popup} from "react-leaflet";


class VisOnMap {

    state = ({
        todo:null
    })
    lat = 0.0;
    lng = 0.0;
    heading = 0;
     setState(p_res){
         this.state.todo = p_res.data
    }
     getState() {
        return(
            JSON.stringify( this.state.todo, null, 2)
        )
    }
     componentDidMount = () => {
        axios.get('https://biocache-ws.biodiversityatlas.at/occurrences/search?q=Bombina%20Bombina&pageSize=100')
            .then(res=>{
                 this.setState(JSON.stringify(res.data))
            })
            .catch(err=>console.log(err))
        console.log( this.getState());
    }
    constructor() {
         this.componentDidMount()
         this.myfun()
    }

    setLat = (p_lat) => {
         this.lat = p_lat
    }
    getLat = () => {
        return (
             this.lat
        )
    }
    getLng = () => {
        return (
            this.lng
        )
    }
    setLng = (p_lng) => {
         this.lng = p_lng
    }
    setHeading = (p_heading) => {
         this.heading = p_heading
    }
    myfun = () => {
        console.log( this.getState())
         this.setLat( this.getState() + 0.00001);
         this.setLng( this.getState() + 0.00001);
         this.setHeading( this.heading+5);
    };
    render() {
        return (
            <MapContainer>
                <TileLayer>
                <Marker position={[ this.getLat(),  this.getLng()]} rotationAngle={this.heading} rotationOrigin="center">
                    <Popup>
                        A pretty CSS3 popup. <br /> Easily customizable.
                    </Popup>
                </Marker>
                </TileLayer>
            </MapContainer>
        )
    }
}

export default VisOnMap

Map.jsx

import React, { useEffect } from "react";
import L from "leaflet";
import {MapContainer, Marker, Popup, TileLayer} from "react-leaflet"
import axios from "axios";
import VisionMap from "./VisonMap"


const MapApply = () => {
    // Create our map tile layer:

    const MAP_TILE = L.tileLayer(`https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={token}`, {
        attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
        center: [-0.113049, 51.498568],
        zoom: 14,
        pitch : 56,
        bearing : 60,
        baseLayer: new L.TileLayer('base', {
            urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png?access_token={token}',
            subdomains: ['a','b','c','d'],
            attribution: '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>'
        }),
        id: 'mapbox.satellite',
        tileSize: 256,
        zoomOffset: 0,
        token: ''
    });
    // Define the styles that are to be passed to the map instance:
    const mapStyles = {
        overflow: "hidden",
        width: "100%",
        height: "100vh"
    };

    // Define an object literal with params that will be passed to the map:
    const mapParams = {
        center: [37.0902, -95.7129],
        zoom: 3,
        zoomControl: false,
        maxBounds: L.latLngBounds(L.latLng(-150, -240), L.latLng(150, 240)),
        layers: [MAP_TILE]
    };

    useEffect(() => {
        const map = ("map", mapParams);
    }, []);


    return (
        <div>
            <div id="map" style={mapStyles}>

            </div>
        </div>
        // Here not write
    )
}

export default MapApply

App.js

import './App.css';
import React, { useEffect, useRef, Component} from "react";
import axios from "axios";
import L from "leaflet";
import MapApply from "./Map";
import VisOnMap from "./VisonMap";

class App extends Component{

    render(){
        return (
            <div>
                <MapApply>
                </MapApply>
            </div>
        )
    }
}

export default App;

indes.js

import React,{Component} from 'react'
import ReactDOM from 'react-dom';
import axios from 'axios';
import './index.css';
import App from './App';
import VisOnMap from './VisonMap';


import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
      <App>
          <VisOnMap></VisOnMap>
      </App>
  </React.StrictMode>,
  document.getElementById('root')
);

reportWebVitals();
1 Answers

This is your issue:

<Marker position={[ this.getLat(),  this.getLng()]} />

First of all, the position is crafted from functions that are called, and in being called, return a state variable. That means that when Marker renders, it calls this.getlat and this.getLng, and returns the values as they are on mount. That's it. Even when the state of VisOnMap updates, that doesn't mean that this.getLat or this.getLng are called again and upate the marker position. These are not references to state variables, but rather functions that return a state variable, but they are only called on the mount of Marker.

Try this

<Marker position={[ this.state.lat,  this.state.lng]} />
Related