LiveBy / react-leaflet-choropleth

Component for React-Leaflet that adds choropleth functionality
ISC License
16 stars 8 forks source link

Not rendering new geojson data/prop immediately #3

Closed gijs closed 7 years ago

gijs commented 8 years ago

Hi,

I'm using react-leaflet-choropleth together with redux, and I have trouble updating the geojson via data={} I'm also using HMR.

Now, on initial render, all works fine:

const choropleth = <Choropleth
                                   data={this.props.results}
                                   ...

but when the component receives new results props, they don't get rendered. When I manually replace this.props.results with [] and save the file, then change it back and save again, the new results props do get rendered.

I hope I explained that in a clear enough way... Thanks in advance!

jgimbel commented 8 years ago

I will look into the issue this weekend. In theory that should be already set up, I just don't have a project to show an example right now. I do know colors will update when a redux store changes. Give me a day or two to test this.

gijs commented 8 years ago

After some further investigation I noticed that the react-leaflet documentation says that GeoJson is not a dynamic property: https://github.com/PaulLeCam/react-leaflet/blob/master/docs/Components.md#geojson

The properties documented as dynamic properties are updated using the relevant Leaflet setter, other properties will not update the component when they are changed after the component is mounted.

So that might be the root cause. I've opted for this approach using a wrapper around the GeoJson class.

import React from 'react';
import { GeoJson } from 'react-leaflet';

export default class GeoJsonUpdatable extends GeoJson {
  componentWillReceiveProps(prevProps) {
    if (prevProps.data !== this.props.data) {
      this.leafletElement.clearLayers();
    }
  }

  componentDidUpdate(prevProps) {
    if (prevProps.data !== this.props.data) {
      this.leafletElement.addData(this.props.data);
    }
  }
}

GeoJsonUpdatable.propTypes = {
  data: React.PropTypes.object.isRequired,
};
jgimbel commented 8 years ago

Yes, data on the GeoJson component is not dynamic, although when data is passed in as an array, I map through each feature given and create and GeoJson component. This gives the feel of being dynamic without actually being dynamic(Using reacts lifecycle).

jgimbel commented 8 years ago

Hello again,

I recently ran into a similar problem as described above. When I started sorting my geojson array by a value, it obviously changed the order of the array, and the colors would be incorrect. I tracked this down to a bug I introduced to react by using the index of the array as the key.

data.map((datum, idx) => (
  <GeoJSON key={idx} ... />
)

To fix this I added a identity function to the Choropleth props.

data.map((datum, idx) => (
  <GeoJSON key={ (identity) ? identity(datum) : idx } ... />
)

This is used to identify each GeoJSON Shape. I hope this fixes your original problem.

gijs commented 8 years ago

Thanks for sharing this. I'll see if I can find time to test it and let you know if it solves the original problem indeed.

aqueiros commented 6 years ago

Greetings, I was also having problems updating the Choropleth data dynamically and after bumping into this issue, I can confirm that this solved it for me. :)

This is what my renderer looks like:

<Choropleth
    identity={(feature) => this.getIdentity(feature)}
    data={this.props.choroplethMap}
    valueProperty={(feature) => feature.properties.amount}
    scale={['red', 'yellow', 'green']}
    steps={20}
    mode="e" // mode can be 'e'(equidistant), 'q'(quantile) or 'k' (k-means). more info on https://gka.github.io/chroma.js/
    onEachFeature={(feature, layer) => layer.bindPopup(`Amount:${feature.properties.amount}`)}
    style={choroplathStyle}
 />

then my getIdentity looks like this:

  getIdentity(feature) {
    return hash(feature);   // generates unique hash from the feature object using object-hash library
  }

Hope this helps future people. Best regards!

zcemycl commented 3 years ago

I also had this problem, but solved it by clearing the state first, then updating it.

dispatch({type:'object',key:'data',value:null}) # clear the state
# do sth
dispatch({type:'object',key:'data',value:json['polygons']}) # update

## Then this will give you immediate update.
<Choropleth data={data} mode="e"/>