Search code examples
javascriptjsonreactjsgeojsonreact-leaflet

React component (GeoJSON) not re-rendering on state change


I use the react-leaflet library to create a simple geoportal in which the user can change the color, visibility and transparency of the vector layers. I took the sliders to change the color from the React color collection. The problem is that after changing the style in the state of my component with GeoJSON, my vector layer does not change its color - it does not render again.

Here is my component with GeoJSON layer (there may be a few unnecessary elements that resulted from repeated attempts to fix the problem) :

import React from 'react';
import PropTypes from 'prop-types';
import { GeoJSON } from 'react-leaflet';

class VectorLayers extends React.Component{
    constructor(props){
        super(props);
        this.state={
            key: this.props.layer.name,
            data: this.props.layer,
            style: {
                weight: 0,
                fillColor: this.props.color,
                fillOpacity: this.props.color,
                styleChanged: false
            },
        }
    }

    componentDidUpdate(prevProps, prevState) {
        if(this.state.style !== prevState.style) {
            let newStatus = !this.state.style.styleChanged
            this.setState({newStatus})
        }
    }

    static getDerivedStateFromProps(nextProps, prevState){
        if(nextProps.color!==prevState.style.fillColor){
            return {style: {
                weight: 0,
                fillColor : nextProps.color,
                fillOpacity : nextProps.color
            }}
        }
        else return null;
    }
    render(){
        return (
            <GeoJSON
                key={ this.state.key }
                data={ this.state.data }
                style={ this.state.style }
            />
        );
    }
}

VectorLayers.propTypes = {
    layer: PropTypes.shape().isRequired,
    color: PropTypes.string.isRequired
};

export default VectorLayers;

And this is a fragment of my App.js code with props for vector layer:

            {
                this.state.layers.map((layer) => ( 
                    this.state.checkboxes[layer.name] && (
                        <VectorLayers
                            key={ layer.name }
                            layer={ layer }
                            color={ this.state.colors[layer.name] }
                        />
                    )
                ))
            }

The function to change the color and the components with the sliders work well, so I do not see the need to add them here. I will be very grateful for your help in finding a solution!


Solution

  • Edit: Change your style to a function like so:

    style={() => {return ({fillColor: this.state.style.fillColor})}}

    Looks like the key you use never changes so react doesn't bother re-rendering your GeoJSON. Try something like

    key={ this.state.key + this.state.style.fillColor }

    Also it's weird that you're assigning opacity a color like fillOpacity: this.props.color,

    Shouldn't that be a number between 0 and 1?