LoF10
LoF10

Reputation: 2127

React: How to map a geojson via fetch call to state using leaflet?

I am trying to map out a geojson that I am fetching in react and using react-leaflet. I am able to map the geojson when I import it locally. Now I am fetching the raw data via https and then setting state to try to pass that state as props. But nothing maps from this.state.geojson.

I think I might be setting state wrong or misunderstanding how the rendering works. Some guidance would be appreciated. Below is some of the code:

App.js

...
  fetchData = async () => {
      let data = await
        fetch(
          "https://raw.githubusercontent.com/timwis/leaflet-choropleth/gh-pages/examples/basic/crimes_by_district.geojson"
          )
          .then((response) => response.json())
          .then((geojson) => {
            return geojson
          })

      console.log("my_data: ", data)
      this.setState({ geojson: data, loaded: 2 })
      return data
}
...

 {/** MAP */}
            <div>
              {this.state.geojson && <Leaf
                viewPort={this.state.viewPort}
                geojson={this.state.geojson} 
              />}
            </div>
...

Leaf.js

...
<Map>
...
<Choro
  geojson={this.props.geojson}
/>
</Map>

Choro.js

import { useEffect } from 'react';
import { useLeaflet } from "react-leaflet";
var L = require('leaflet')
require('leaflet-choropleth')


function Choro(props) {
    const { map } = useLeaflet();
  
    useEffect(() => {
      fetch(
        //"https://raw.githubusercontent.com/timwis/leaflet-choropleth/gh-pages/examples/basic/crimes_by_district.geojson"
        `${props.geojson}`  
      )
        .then((response) => response.json())
        .then((geojson) => {
          L.choropleth(geojson, {
            valueProperty: "DIFF", // which property in the features to use
            scale: ["white", "red"], // chroma.js scale - include as many as you like
            steps: 5, // number of breaks or steps in range
            mode: "q", // q for quantile, e for equidistant, k for k-means
            //style,
            onEachFeature: function (feature, layer) {
              layer.bindPopup(
                "Total " +
                  feature.properties.DIFF +
                  "<br>" //+
                  // feature.properties.incidents.toLocaleString() +
                  // " incidents"
              );
            }
          }).addTo(map);
        });
    }, []);
  
    return null;
 }

 export default Choro;

Upvotes: 1

Views: 1647

Answers (1)

kboul
kboul

Reputation: 14570

Change of state should occur inside then and not outside:

fetchData =  () => {
      fetch(
          "https://raw.githubusercontent.com/timwis/leaflet-choropleth/gh-pages/examples/basic/crimes_by_district.geojson"
          )
          .then((response) => response.json())
          .then((geojson) => {
             console.log("my_data: ", geojson);
             this.setState({ geojson, loaded: 2 })

          })

}

However, I am not still sure what you are doing because you are fetching the geojson on App and then you pass the data to Leaf and then to Choro (this is called prop drilling) and then you are using the geojson as a url to re fetch the data. If you have fetched the data on App why to re fetch them on Choro? And most importantly you use as url the geojson data. Take another look on your code.

Last but not least when you are using then then you cannot use at the same time async await because these two serve exactly the same purpose. They are used to make an async call in a synchronous way.

this is how it should be demo

Upvotes: 2

Related Questions