Closed davidascher closed 8 years ago
I'm guessing this bug isn't w/ choropleth but with my usage of react-leaflet, now that I look at the code a bit deeper.
onEachFeature={(feature, layer) => layer.bindPopup(this.labelPerCountry(feature))}
is most likely your problem.
onEachFeature
will only be run when the leafletElement is mounted (Reference). Hence the popup not updating on each render call. Instead the common solution is to use the Popup
component as a child of geojson, so on each render the popup component will checks whether it should be updated(Example). The problem here is that you are not able to do something as simple as adding the children...
<Choropleth
data={geojson}
valueProperty={this.numCasesPerCountry}
scale={scale}
visible={this.isCountryListed}
steps={5}
mode='e'
style={style}
>
<Popup>
{geojson.properties.name /*bad because the geojson is an array */}
</Popup>
</Choropleth>
or mapping through all the geojson features.
//bad because this creates multiple choropleths, and data is not shared between.
geojson.map(country => (
<Choropleth
data={geojson}
valueProperty={this.numCasesPerCountry}
scale={scale}
visible={this.isCountryListed}
steps={5}
mode='e'
style={style}
>
<Popup>
{contry.properties.name}
</Popup>
</Choropleth>
)
The right solution will require the way we pass props to change, so that children
recieve the feature they are rendered inside. (Like react-leaflet#mapLayer)
const CountryName = ({ feature }) => (
<Popup>
{feature.properties.name}
<Popup>
)
...
<Choropleth
data={geojson}
valueProperty={this.numCasesPerCountry}
scale={scale}
visible={this.isCountryListed}
steps={5}
mode='e'
style={style}
>
<CountryName />
</Choropleth>
Apologies for the noise.
Fixed it, by using code like:
onEachFeature(feature, layer) {
let labelPerCountry = this.labelPerCountry;
layer.on({
click: function(event) {
var popup = L.popup()
.setLatLng(event.latlng)
.setContent(labelPerCountry(feature))
.openOn(layer._map);
}
});
}
and:
<Choropleth
data={geojson}
valueProperty={this.numCasesPerCountry}
scale={scale}
visible={this.isCountryListed}
onEachFeature={this.onEachFeature}
steps={5}
mode='e'
style={style}
/>
Is there anything that you see as problematic w/ the above?
Seems like an elegant way of handling the tooltip without dealing with flux store/state. I am going to work on allowing children as a option for anyone that might need it later.
Children passed to the choropleth component are now passed to each GeoJSON component. To get the current shape, feature
is assigned in its props. This makes the solution I mentioned earlier now available, in case you need to use something like state or flux/redux to handle changes.
TL;DR: tooltips aren't regenerated when state changes.
I have a working (yea!) use of
react-leaflet
andreact-leaflet-choropleth
, which uses geoJSON data and creates a cloropleth map based on an elasticsearch query. The elasticsearch query is triggered on thecomponentWillMount()
method of the react component which includes the choropleth.The render method is simple:
And I have callbacks defined for all three methods. The problem is that when the component
state
changes, the feature color is updated, but the label is not, as indicated by this screengrab, which shows that Italy has a high number of cases, is colored appropriately, but its tooltip isn't up to date:Note that the
labelPerCountry
is only called once.Am I right that this is a bug? I suspect that
react-leaflet
's third technical consideration:is relevant, but I haven't dug into either codebase to unpack it.