I am just a beginner in React, and I was looking for an easier way to setting status. One important note is that it was inside a functional component.
const [ personState, setPersonsState ] = useState({
persons: [
{ name : 'Max', age : 28 },
{ name : 'Manu', age : 29 },
{ name : 'Stephanie', age : 26 }
]
});
I know the way usually is something like this, and this works just fine.
setPersonsState({
persons: [
{ name : 'Max', age : 28 },
{ name : 'Ati', age : 29 },
{ name : 'Stephanie', age : 26 }
]
But I think it's hard to type it in manually every time, so I tried to make my life easier.
const newState = personState;
newState.persons[1].name = 'Ati';
setPersonsState(newState)
This didn't work, and I don't know why.
When I console.log them out it successfully changes, but for some reason the state isn't refreshing, although I use the set command.
I also noticed some strange behavior from React, when I used this newState.persons[1].name = 'Ati';
command it also changed the personState
variable.
So both the personState
and the newState
variable looked like this in the console.
{persons: Array(3)}
persons: Array(3)
0: {name: "Max", age: 28}
1: {name: "Ati", age: 29}
2: {name: "Stephanie", age: 26}
length: 3
__proto__: Array(0)
__proto__: Object
I would appreciate any help or explanation why the this doesn't work.
When you are doing this line const newState = personState;
You are not copying the object in personState to newState, but you are taking a referrence of personState and making newState refer to that.
When you make a change to newState, it's like you are changing personState, because referrence for both of these variables is the same. You are directly mutating a state object which is a no-no in React because it doesn't go with the lifecycle, and that is why you are getting this strange behaviour.
If you want to copy the object content to this new variable, you need to do:
const newState = Object.assign({}, personState)
or use Spread syntax
const newState = { ...personState }
After that you can go about setting the state with the setPersonState
Note: If you have nested objects, these above given methods will only make a shallow copy meaning only the first level values will be copied.
If you want to make a deep copy of the object, you'll either have to do multiple object spreads (which is a common pattern in redux state management) e.g.
let state = {a: "val", b: { c: "val" }}
let newState = {
...state,
b: {
...state.b
}
}
or use lodash's deepClone
e.g.
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);