Phil Birnie
Phil Birnie

Reputation: 1134

React + Mapbox GL: State of Array of Map Components not updating on Map Event

I am attempting to create a map whereby a user can click counties on a map and the clicked counties will be highlighted like so:

Photo of Highlighted Counties

The Problem

I have been able to create a working prototype aside from one major problem -- setting the state when a county is clicked is always based on the original state instead of the updated state. I'm using county FIPS ids, so if I have a list of counties like so:

[39049, 39159] and then I add 39023, the updated array will be [39049, 39159, 39023]. However, a subsequent addition (say 39024) will change the updated array to [39049, 39159, 39024] instead of what I would expect: [39049, 39159, 39023, 39024]

Here is a JSFiddle that demonstrates the problem:

jsfiddle

And this is the pertinent code I'm using to update the county list:

 componentDidMount() {
    const { lng, lat, zoom, counties } = this.state;

     ...

     map.on('click', 'counties', (e) => {
            map.getCanvas().style.cursor = 'pointer';

            // Use the first found feature.
            const feature = e.features[0];

            const {FIPS} = feature.properties;
            
            let updatedCounties;
            
            if(counties.includes(FIPS)) {
                updatedCounties = counties.filter(el => el !== FIPS);
            } else {
                updatedCounties = counties.concat([FIPS]);         
            }
            
            this.setState({
                counties: updatedCounties
            });
            
            map.setFilter('counties-highlighted', [
                'in',
                'FIPS',
            ...updatedCounties
            ]);
        });
  }

Updating single values (like the center of the map or zoom) appear not to be a problem because it's a wholesale overwrite of the value vs modifying an array.

Things I've tried

  1. I've found that if I mutate the original counties value, it works as I would expect, but I know that is bad practice.

Upvotes: 0

Views: 1046

Answers (1)

Pandaiolo
Pandaiolo

Reputation: 11586

I think that you "locked" your initial state values in a javascript closure, causing them to stay the same in your event handler callback, even after the state did change.

You could try to get the state from within the event handler like this:

 componentDidMount() {

     map.on('click', 'counties', (e) => {
          const { lng, lat, zoom, counties } = this.state;

          // use the values that should be current here
            
     });
 }

Upvotes: 1

Related Questions