3
votes

I'm trying to incorporate React-Leaflet into my Create React App. I am able to overlay GeoJSON data on a base map, but I cannot register clicks on this layer.

In investigating this issue, I found the following jsfiddle, https://jsfiddle.net/n7jmqg1s/6/, which registers events when the shapes are clicked as evidenced by the onEachFeature function:

onEachFeature(feature, layer) {
console.log(arguments)
const func = (e)=>{console.log("Click")};

layer.on({
    click: func
});
}

I tried copying and pasting this into my react app, but it doesn't work there. The only thing I changed was instead of window.React/window.LeafletReact I used the es6 import. I don't this this would cause the issue, but I suppose it's possible.

I looked at the arguments from the onEachFeature function. In the jsfiddle, I get 2 arguments--what look to be the feature and layer data. In my copied example, however, I get 3 arguments the first two of which are empty and the third which contains an object with many things including (enqueueCallback : (publicInstance, callback, callerName))

I realize that this is somewhat vague, but I'm hoping that this issue is easily identifiable as a misunderstanding with React or leaflet. I think it has something to do with the fact that I'm not passing the right scope or manipulating the DOM directly or something. But I'm not sure. I would greatly appreciate any help.

Here is my component code:

    import React from 'react';
import { Map, TileLayer, Marker, Popup, GeoJSON } from 'react-leaflet';

export default class SimpleExample extends React.Component {
  constructor() {
    super();
    this.state = {
      lat: 51.505,
      lng: -0.09,
      zoom: 8,
    };
  }

 onEachFeature = (feature, layer) => {
    layer.on({
      click: this.clickToFeature.bind(this)
    });
  }

  clickToFeature = (e) => {
     var layer = e.target;
     console.log("I clicked on " ,layer.feature.properties.name);

  }

  render() {
    const position = [this.state.lat, this.state.lng];
    const geojsonObject = {
        'type': 'FeatureCollection',
        'crs': {
          'type': 'name',
          'properties': {
            'name': 'EPSG:3857'
          }
        },
        'features': [{
          'type': 'Feature',
          'geometry': {
            'type': 'MultiPolygon',
            'coordinates': [
              [[[-0.09, 51.505], [-0.09, 51.59], [-0.12, 51.59], [-0.12, 51.505]]],
              [[[-0.09, 51.305], [-0.09, 51.39], [-0.12, 51.39], [-0.12, 51.305]]]
            ]
          }
        }]
      };
    return (
      <Map center={position} zoom={this.state.zoom} ref='map'>
        <TileLayer
          attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
          url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
        />
        <GeoJSON
            ref="geojson"
            data={geojsonObject}
            onEachFeature={this.onEachFeature}
          />
      </Map>
    );
  }
}
2
try with onEachFeature={this.onEachFeature.bind(this)} - Alex Parij
interestingly, doing that gives me: Uncaught TypeError: Cannot read property 'bind' of undefined - joshlevy89

2 Answers

6
votes

First you define your map in the render function :

   <LeafletMap
      ref='map'>
      <GeoJson
        ref="geojson"
        data={this.props.data}
        onEachFeature={this.onEachFeature.bind(this)}
      />
     </LeafletMap>

then you define an onEachFeature function listing all the listeners

onEachFeature(feature, layer) {
    layer.on({
      mouseover: this.highlightFeature.bind(this),
      mouseout: this.resetHighlight.bind(this),
      click: this.clickToFeature.bind(this)
    });
  }

then you define each event handle function for example click function or mouse over

 clickToFeature(e) {
     var layer = e.target;
     console.log("I clicked on " + layer.feature.properties.name);

  }

without seeing the Leaflet tag code and how you call onEachFeature, I can't really help with the ES6 example you have. It's possible that you do not call it like in the JSFiddle example

  onEachFeature={this.onEachFeature}
-1
votes

For ES6 you should use this:

onEachFeature = (feature, layer) => {
  layer.on({
    click: this.clickToFeature
  });
}

Instead of this:

onEachFeature = (feature, layer) => {
  layer.on({
    click: this.clickToFeature.bind(this)
  });
}