user13286
user13286

Reputation: 3075

React - setState within a for loop to add data to array

I have an array of locations with lat/lng coordinates. I am using a distance calculating function to determine the distance of each location from the center of a Google map in order to sort the array by distance, as well as render the distance in my app. Currently I am doing that like so:

for(var i=0; i < this.state.locations.length; i++) {
    this.state.locations[i]['distance'] = this.calculateDistance(this.state.locations[i].coords, this.state);
}

const sortedlocations = this.state.locations.sort((a, b) => a.distance - b.distance);
this.setState({locations: sortedlocations});

This is actually working as desired, but I am getting a warning Do not mutate state directly. Use setState() so I would like to get it working the correct way. I am not quite sure how to use setState within this for loop. I tried below just taking a stab in the dark, but it didnt work haha:

for(var i=0; i < this.state.locations.length; i++) {
    this.setState({
        locations[i]['distance']: = this.calculateDistance(this.state.locations[i].coords, this.state);
    })
}

Here is an example of what this.state.locations looks like:

[
  {
    "location": "Lorem Ipsum",
    "description": "Lorem Ipsum"
    "coords": {
      "lat": -50.12424,
      "lng": 80.04562
    }
  },
  {
    "location": "Lorem Ipsum 2",
    "description": "Lorem Ipsum 2"
    "coords": {
      "lat": -37.10005,
      "lng": 65.55088
    }
  },
  {
    "location": "Lorem Ipsum 3",
    "description": "Lorem Ipsum 3"
    "coords": {
      "lat": -56.39949,
      "lng": -98.10049
    }
  },
  {
    "location": "Lorem Ipsum 4",
    "description": "Lorem Ipsum 4"
    "coords": {
      "lat": -67.61780,
      "lng": 145.47068
    }
  }
]

Upvotes: 0

Views: 35

Answers (1)

Joshua Obritsch
Joshua Obritsch

Reputation: 1293

You should never mutate state directly. Always create a copy, mutate the copy and then call setState with the new copy so that it will create a new object reference in memory.

Instead of this:

for(var i=0; i < this.state.locations.length; i++) {
    this.state.locations[i]['distance'] = this.calculateDistance(this.state.locations[i].coords, this.state);
}

Try this:

const locations = [ ...this.state.locations ];

for(var i=0; i < locations.length; i++) {
    locations[i]['distance'] = this.calculateDistance(locations[i].coords, this.state);
}

Then do the rest like this:

const sortedlocations = locations.sort((a, b) => a.distance - b.distance);
this.setState({locations: sortedlocations});

Upvotes: 1

Related Questions