6

I'm trying to visualize a GeoJSON layer on Leaflet using React-Leaflet library. My mental process is:

  1. Click on the button which calls a method named getHospitals()
  2. getHospitals() gets the geojson layer from the backend using axios
  3. The geojson layer is saved in a variable
  4. Then, create a reference which will passed to the geojson component in order to 'update' the component (I don't know if it's correct)
  5. Update the component state with the layer and the reference (this.setState())
  6. The component renders the new geojson

The problem is the geojson doesn't appear on the map. This is the code:

import React, { Component } from "react";
import {
  MapContainer,
  TileLayer,
  LayersControl,
  ScaleControl,
  GeoJSON,
} from "react-leaflet";
import "leaflet/dist/leaflet.css";
import axios from "axios";

import "./Mapa.css";

export class Mapa extends Component {
  state = {
    geoJSON: null,
    reference: null,
  };

  /* Definición de estilos del mapa */
  style = {
    height: 600,
    margin: 10,
  };

  getHospitals = async () => {
    let hospitals = await axios.get(
      "https://cartovis-server.herokuapp.com/hospitales"
    );

    let reference = React.createRef();

    this.setState({
      geoJSON: hospitals.data,
      reference: reference
    });
  };

  render() {
    return (
      <div id="viewer">
        <MapContainer center={[38, -1]} zoom="5" style={this.style}>
          <GeoJSON
            attribution="Capa de Hospitales de ESRI"
            data={this.state.geoJSON}
            ref={this.reference}
          />
          <ScaleControl />
          <LayersControl>
            <LayersControl.BaseLayer checked name="OpenStreetMap">
              <TileLayer
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
              />
            </LayersControl.BaseLayer>
          </LayersControl>
        </MapContainer>
        <div className="otherLayers">
          <h4>Hospitales</h4>
          <button className="btn btn-primary" onClick={this.getHospitals}>
            Ver
          </button>
        </div>
      </div>
    );
  }
}

export default Mapa;

Any idea?

2
  • I'm not familiar with axios AJAX library, but hospitals.data probably contains GeoJSON as string, not object, so before using it you have to parse it: JSON.parse(hospitals.data).
    – TomazicM
    Commented Nov 24, 2020 at 17:34
  • axios returns an object. If I parse the response to a JSON, it returns an error: Unhandled Rejection (SyntaxError): JSON.parse: unexpected character at line 1 column 2 of the JSON data
    – VicentGN
    Commented Nov 24, 2020 at 18:12

1 Answer 1

5

GeoJSON:

data is immutable. So the layer is not re-rendered when the prop changes.

You can add the following check to see the layer on the map:

{this.state.geoJSON && (
  <GeoJSON
    attribution="Capa de Hospitales de ESRI"
    data={this.state.geoJSON}
  />
)}

That way the layer is mounted when geoJSON is not null.

3
  • It works, thanks! So, the component only appears when the state contains the geojson isn't it?
    – VicentGN
    Commented Nov 24, 2020 at 18:40
  • The idea is that if the component cannot be re-rendered on data change, let's insert it into the DOM when the geojson is not null. There might be more elegant solutions to all of this. Commented Nov 24, 2020 at 18:45
  • I see. Ok! Thanks for your solution.
    – VicentGN
    Commented Nov 24, 2020 at 18:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.