fes
fes

Reputation: 2525

React Array in State Mutating

I don't know if there is a conflict in the libraries I'm using but for some reason or its, the latest react but when I'm updating an array from the state, it's mutating it even though I haven't called setState. Is there a special case for Arrays in the state that I'm not aware of?

constructor(props){
    super(props);

    this.state = {
      data: [
        { id: 1, name: 'hello' },
        { id: 2, name: 'world' },
        { id: 3, name: 'once' }
      ]
    }
}
performUpdate() {
  const { data } = this.state;

  var current_data = data.slice();

  current_data[0].name = 'helloooooo';

  console.log(data)

  // it shows data.id 1 now has name: 'helloooooo'
}

Since I made a copy of the array from state, shouldn't the state be updated only if I call

this.setState({
  data: current_data
})

Upvotes: 2

Views: 525

Answers (2)

Giorgi Moniava
Giorgi Moniava

Reputation: 28685

Since I made a copy of the array from state, shouldn't the state be updated only if I call

You made a shallow copy. This:

  current_data[0].name 

is same as saying:

this.state.data[0].name

this.state.data[0] and current_data[0] point to same object, due to shallow copy; even though slice returned new array, its elements basically point to same objects as the elements from the original array.

You maybe interested in how to immutably modify one of array elements.

Upvotes: 4

Kraylog
Kraylog

Reputation: 7563

slice performs a shallow copy of the array - meaning that only the pointers to the objects contained in the array are copied, not the objects themselves.

This means that after the slice you have two arrays pointing at the same objects. Naturally, then, changing an object in one, will change it in the other.

Instead, what you want to do is create a deep clone. You can use immutability-helper or something like Lodash to achieve this.

Upvotes: 2

Related Questions