hi (I also posted this on stackoverflow )
I'm using the deck.gl GeoJsonLayer to display regions on a map.
through an event, I was able to make these regions selectable.
what I am struggling with, is to change the color of a feature in the feature selection after clicking on it.
this is the render layer function (adapted from here)
_renderLayers(props) {
const { geofeats } = props;
return [
new GeoJsonLayer({
id: 'geojson',
data: geofeats,
opacity: 0.8,
stroked: true,
filled: true,
extruded: true,
wireframe: true,
getElevation: f => 10000,
getFillColor: f =>
{
if(f.properties.selected)
{
return [200, 200, 100];
} else return [200, 100, 150];
},
getLineColor: [255, 255, 255],
pickable: true,
onHover: this._onHover,
onClick: this._onClick
})
];
}
the problem is, when I update the selection state of a feature in the feature collection via setState(), the rendering is not updated even though the state change is represented in the data..
this is how I relay the 'geofeats' object:
render() {
const {features} = this.state;
const {mapStyle = 'mapbox://styles/mapbox/light-v9'} = this.props;
return (
<DeckGL
layers={this._renderLayers({geofeats: features})}
effects={this._effects}
initialViewState={INITIAL_VIEW_STATE}
controller={true}
>
<StaticMap
reuseMaps
mapStyle={mapStyle}
preventStyleDiffing={true}
mapboxApiAccessToken={MAPBOX_TOKEN}
/>
{this._renderTooltip}
</DeckGL>
);
}
I tried it via setState instead of via props - but the result is the same. the feature collection is handed over to the GeoJsonLayer but never updated.
could someone tell me, what I'm doing wrong?
I did not find any code samples where the render style was updated through interaction during runtime (only examples for data filtering)
Check out the updateTriggers prop.
thank you! however, I'm not changing an external data point that should cause the trigger - I change a data property, so the update should be triggered implicitly.
I reconstruct the problem in this gist:
https://gist.github.com/jaronimoe/efdbb58b3f52c2aac63362a921802cfe
here hovering on the map changes the data property (as proven in the console output) but the rendering does not reflect the updated data state.
It's the same thing. Without evaluating the functions there's no way for deck.gl to tell that your data changed deeply, and it's important for perf that we don't reevaluate them every frame. updateTrigger is a way for you to notify deck.gl that things have changed.
I see - but how would I specify the trigger attribute for a data attribute of the geojson object?
I tried like this:
updateTriggers: d => {
getFillColor: [ d.properties.selected]
},
but it did not work. and I'm not sure in which other way to supply the data property..
updateTriggers is an object, not a callback.
I had to point to the hovered/selected object properties in order to get it to work:
updateTriggers: {
getFillColor: [
this.state.hoveredObject
? this.state.hoveredObject.properties.id
: null
]
},
@Pessimistress I'm trying to do the same thing but the rerender of the layer takes around 3 seconds and the layer isn't interactive until then. Was wondering if I'm missing something. On mobile it works great and has the same behaviour I want to achieve on desktop (tapping on an item changes the colour though making it 'selected'). Also the whole layer is rendered just fine the first time. The rendering is only slow when it's triggered by the updateTrigger.
Here's what I have so far:
`const App = () => {
const [selectedItem, setSelectedItem] = useState(null);
const layers = [
new H3ClusterLayer({
id: 'h3-cluster-layer',
data,
pickable: true,
stroked: true,
filled: true,
extruded: false,
getHexagons: d => d.hexIds,
getFillColor: hexagon => {
if (selectedItem && hexagon.hexIds[0] === selectedItem.hexIds[0]) return [25,116,210]
if (hexagon.mean === undefined) return [122, 122, 122];
return [255, (1 - hexagon.mean / 500) * 255, 0];
},
updateTriggers: {
getFillColor: [selectedItem]
},
getLineColor: [255, 255, 255],
lineWidthMinPixels: 1,
opacity: 0.03,
autoHighlight: true,
highlightColor: [142,223,255],
}),
];
return (
controller={true}
layers={layers}
onClick={(info, event) => {
// event bubble cancelation doesn't work between react components and deck.gl
if (event.target !== document.getElementById('view-default-view')) return;
setSelectedItem(info.object)
}}
>
<StaticMap mapboxApiAccessToken={MAPBOX_ACCESS_TOKEN} />
{selectedItem && <Details selectedItem={selectedItem} />}
</DeckGL>
);
}`
Please ignore me, it works perfectly if I only pass the id to updateTriggers :)