2
votes

First of all, give thanks for reading my question and try to help me and apologize for my English.

In a react component I have and input where add files and upload geojson file. After I crete the source layer with the url uploaded (CORS are enabled) and show layer, but when I move mouse and hover over feature, that feature dont have id and state is empty. However, If I add a vector layer and I move mouse hover over feature has id and state.

I found information and if not show id is because I dont add the geojson layer correctly.

Info1

Examples using map.setFeatureState() like this https://www.mapbox.com/mapbox-gl-js/example/hover-styles/ require that a user include an integer parent id value in their geojson or vector tile source.

Info2

state(Object)A set of key-value pairs. The values should be valid JSON types. This method requires the feature.id attribute on data sets. For GeoJSON sources without feature ids, set the generateIds option in the GeoJSONSourceSpecification to auto-assign them. This option assigns ids based on a feature's index in the source data. If you change feature data using map.getSource('some id').setData(..), you may need to re-apply state taking into account updated id values.

REACT Mapbox Documentation

Here is my code:

<MapBox
    style={this.props.mapStyle}
    center={this.props.viewport.center}
    zoom={this.props.viewport.mapZoom}
    pitch={this.props.viewport.pitch}
    minZoom={this.props.viewport.minZoom}
    maxZoom={this.props.viewport.maxZoom}
    onZoom={this.handleZoom}
    onMoveEnd={this.handleMove}
    onMouseMove={this.handleOnMouseMove}
    onMouseDown={this.handleOnMouseDown.bind(this)}
    onMouseUp={this.handleOnMouseUp.bind(this)}
    onStyleLoad={this.handleLoad}
    onError={this.handleError}
    containerStyle={{
       position: 'relative',
       height: '100vh',
       width: this.props.rightDrawer.visible ? 'calc(100vw - 300px)' : '100vw'
}}>

{/* Option 1 */}
{this.state.mapLoaded && this.props.mapGLlayers &&
    this.props.mapGLlayers.map((l, index) => {
        return (
            <div key={index}>                                
                {l.name && l.redraw && l.redraw === true && <Source id={"sourceId_" + l.id} tileJsonSource={l.source} onSourceLoaded={this.handleSourceLoaded} />}                                            
                {l.redraw && l.redraw === true && <Layer type={l.type} id={l.id} sourceId={l.name ? "sourceId_" + l.id : l['source'] ? l['source'] : undefined}
                    sourceLayer={l['source-layer'] ? l['source-layer'] : undefined}
                    filter={l.filter ? l.filter : undefined}
                    paint={l.paint ? l.paint : undefined}
                    layout={l.layout ? l.layout : undefined}
                    before={l.before ? l.before : undefined}
                />}
            </div>
        );
    })
}
</MapBox>



<MapBox
    style={this.props.mapStyle}
    center={this.props.viewport.center}
    zoom={this.props.viewport.mapZoom}
    pitch={this.props.viewport.pitch}
    minZoom={this.props.viewport.minZoom}
    maxZoom={this.props.viewport.maxZoom}
    onZoom={this.handleZoom}
    onMoveEnd={this.handleMove}
    onMouseMove={this.handleOnMouseMove}
    onMouseDown={this.handleOnMouseDown.bind(this)}
    onMouseUp={this.handleOnMouseUp.bind(this)}
    onStyleLoad={this.handleLoad}
    onError={this.handleError}
    containerStyle={{
       position: 'relative',
       height: '100vh',
       width: this.props.rightDrawer.visible ? 'calc(100vw - 300px)' : '100vw'
}}>

{/* Option 2 */}
{this.state.mapLoaded && this.props.mapGLlayers &&
    this.props.mapGLlayers.map((l, index) => {
        return (
            <div key={index}>  
                {   (isGeoJson) ? 
                    (l.name && l.redraw && l.redraw === true && <Source id={"sourceId_" + l.id} geoJsonSource={{ type: l.source.type, data: l.source.data}} onSourceLoaded={this.handleSourceLoaded} />) :
                    (l.name && l.redraw && l.redraw === true && <Source id={"sourceId_" + l.id} tileJsonSource={l.source} onSourceLoaded={this.handleSourceLoaded} />) 
                }                                          
                {l.redraw && l.redraw === true && <Layer type={l.type} id={l.id} sourceId={l.name ? "sourceId_" + l.id : l['source'] ? l['source'] : undefined}
                    sourceLayer={l['source-layer'] ? l['source-layer'] : undefined}
                    filter={l.filter ? l.filter : undefined}
                    paint={l.paint ? l.paint : undefined}
                    layout={l.layout ? l.layout : undefined}
                    before={l.before ? l.before : undefined}
                />}
            </div>
        );
    })
}
1

1 Answers

0
votes

Thanks for your help.

I found a solution. When you are adding the layer you can add a property in source that generate and id for each feature of the layer.

generateId

Optional boolean. Defaults to false. Whether to generate ids for the geojson features. When enabled, the feature.id property will be auto assigned based on its index in the features array, over-writing any previous values.

export const generateLayerFromFile = (layer) => {
    return {
        "id": `${uniqid()}`,
        "order": Number(layer.order),
        "layer": Object.assign({}, layer),
        "name": `${layer.name}`,
        "type": `${layer.type}`,
        "source": {
            "type": String(layer.layer.source.type),
            "data": String(layer.layer.source.url),
            "generateId: true,
        },
        "paint": (layer.paint) ? JSON.parse(layer.paint) : undefined,
        "layout": (layer.layout) ? JSON.parse(layer.layout) : undefined,
        "filter": (layer.filter) ? JSON.parse(layer.filter) : undefined
    };
};