10- Removing the Local State

This method makes me really confused.

If counters is the same as [...this.state.counters], why don’t we just use const counters = this.state.counters? Is the deconstructor necessary?

At the same time, why can we assign { ...counter } to counters[0] when counters is a constant?

Is there a better way to write this method?

The magic and performance of react relies on that you never change the state directly but only via setState(). So we need to make copies of counters and the individual counter we want to update to avoid state changes outside of setState()

You can’t change which object a constant points to. So assigning another array (or any other value) to counters would be an error. But you can change the content of that object.

1 Like

The reason mosh did [...this.state.counters] is because if we use the this.state.counter we would change the state directly which is not what you want to do in react.
So instead we made a copy of the state but it’s exactly the same as this.state.counter .

Then, you get each index of your counter object and clone it at the giving location to have a different counter object than the one in the state.

Simply put, you are copying the state and making a new array, then get the index of each counter in your array and copy each counter object.

You have an original array but you don’t want to change it directly in react, so you make a copy of it to be able to modify it.

I hope it helps you :slightly_smiling_face: :heart:

[…,this.state.counters] copy the state, you can do whatever you want to do without any side-effects. This is the concept of Functional Programming.

You will be confused about the setState will eventually change the state, so why bothered.
Actually is not.The React is kind of state machine. setState will package states in to queue waiting to deal with. They are isolated with each other.

If you Change the state directly.There are many other places use the state will be changed. And also the state waiting in queue will be effected as well. Especially when you build a very large project, this behavios is very danderous. It will cause choas.


Thanks for all the replies! They are all very helpful.

I see why [...this.state.counters] or { ...counter } is used in React to copy the value instead of re-assigning the address.

One thing I don’t understand is why do I have to do counters[index] = {...counter}
before doing counters[index].value++

For the exact same reason we explained. Each entry in the counters Array is a reference or pointer to the respective counter’s value. If we assign a new value directly we would change the value in the current state and that’s something we should avoid.

here’s what I did, is this valid?

handleIncrement = (counter) => {
const value = counter.value++;
this.setState({ value });

Hi Sam.

Thanks for the response. That’s what i thought too. However, I observed that when I commented out the updating via the setState() and was looking at the console.log(), the actual DOM was not getting updated but the console.log() shows that value was being incremented. Hence, I believed that it was not directly updating the state, until it executed the setState() and the app worked.

Anyway, I still followed Mosh’s way. I was just experimenting and tried to validate my suspicion.

Thanks again for the help.


here’s an experiment I made:

const array = [{ id: 1 }, { id: 2 }, { id: 3 }];
const copyArray = array;
copyArray[0].id = 5;
console.log(“array”, array, “copyArray”, copyArray);

array and copyArray have the same result because they’re both pointing at the very same object.
now see what happens when I use the spread operator:

const array = [{ id: 1 }, { id: 2 }, { id: 3 }];
const copyArray = [...array];
copyArray[0].id = 5;
console.log("array", array, "copyArray", copyArray);

In this example the result will again be the same because although I used the spread operator on the array still the object at each index is the same, whereas if I give it a different object completely only copyArray will get changed and array will remain unchanged as follows:

const array = [{ id: 1 }, { id: 2 }, { id: 3 }];
const copyArray = […array];
copyArray[0] = 5;
console.log(“array”, array, “copyArray”, copyArray);

In order to make a change to that object I would have to use the spread operator again as follows:

const array = [{ id: 1 }, { id: 2 }, { id: 3 }];
const copyArray = [...array];
copyArray[0] = { ...array[0] };
copyArray[0].id = 5;
console.log("array", array, "copyArray", copyArray);

Finally, I get array = [{ id: 1 }, { id: 2 }, { id: 3 }] and copyArray = [{ id: 5 }, { id: 2 }, { id: 3 }].

Hope this is helpful! :slightly_smiling_face: