React-mapbox-gl: feature.id missing from dataset

Created on 31 Oct 2018  路  2Comments  路  Source: alex3165/react-mapbox-gl

Hey,

Trying to implement this example:
https://www.mapbox.com/mapbox-gl-js/example/hover-styles

It uses the map method setFeatureState:
https://www.mapbox.com/mapbox-gl-js/api/#map#setfeaturestate

which states:

This method requires the feature.id attribute on data sets.

I can see from the event object that this library is automatically setting a feature.properties.id, but unfortunately that doesn't appear compatible with map.setFeatureState which needs feature.id.

For example this code has no effect:

handleLineMouseEnter = (e) => {
  const {map, feature} = e
  const {properties: {id}, source} = feature
  map.setFeatureState({id, source}, {hover: true})
}

// ...

<Layer
  type="line"
  paint={{
    'line-color': [
      'case', ['boolean', ['feature-state', 'hover'], false],
      '#ff0000',
      '#ff8f33'
    ]
  }}>
  {lines.map((line, idx) => (
    <Feature
      key={idx}
      coordinates={line}
      onMouseEnter={this.handleLineMouseEnter}
    />
  ))}
</Layer>

My naeve suggestion would be that if a user explicitly sets an id prop on the feature, then it could be added to the dataset, ie:

handleLineMouseEnter = (e) => {
  console.log(e.feature.id) // line-a
}

<Feature
    id="line-a"
    coordinates={line}
    onMouseEnter={this.handleLineMouseEnter}
/>
Ready to work

Most helpful comment

Any chance we can get this merged??

All 2 comments

@daviestar I opened a PR to fix this.
You can patch the plugin while this is not merge. Your code should now work as expected (ofc, I tested it before submitting the PR).

Here is another example that will be able to achieve what you wanted to do when the PR will be merged (see #603)

Function called onStyleLoad event:

  onMapLoaded = (map) => {
    this.map = map;
    // This is a copy paste of mapbox code
    this.map.on("mousemove", "tm-countries", (e) => {
      if (e.features.length > 0) {
        if (this.hoveredCountry) {
          this.map.setFeatureState({source: 'countries-source', id: this.hoveredCountry}, { hover: false});
        }
        this.hoveredCountry = e.features[0].id;
        this.map.setFeatureState({source: 'countries-source', id: this.hoveredCountry}, { hover: true});
      }
    });

    this.map.on("mouseleave", "tm-countries", () => {
      if (this.hoveredCountry) {
        this.map.setFeatureState({source: 'countries-source', id: this.hoveredCountry}, { hover: false});
      }
      this.hoveredCountry =  null;
    });
  };
render() {
    const multiPolygonPaint = {
      'fill-color': '#3bb2d0',
      'fill-opacity': ["case",
        ["boolean", ["feature-state", "hover"], false],
        1,
        0.5
      ]
    };

    const {countriesDataGeoJson} = this.state;

    return (
            <Map
              style={...}
              zoom={zoom}
              center={center}
              onStyleLoad={this.onMapLoaded}
            >
                <GeoJSONLayer
                     data={countriesDataGeoJson}
                     fillPaint={multiPolygonPaint}
                     layerOptions={{
                         id: 'tm-countries',
                         type: 'fill',
                     }}
                     id="countries-source"
                />
            </Map>
    );

Any chance we can get this merged??

Was this page helpful?
0 / 5 - 0 ratings

Related issues

appjitsu picture appjitsu  路  3Comments

stereobooster picture stereobooster  路  4Comments

faiq picture faiq  路  4Comments

cyrilchapon picture cyrilchapon  路  3Comments

kolharsam picture kolharsam  路  4Comments