I have this as state in my component const [state, setState] = useState<IEmployee>(employeesInitialState)
And this is the code that is handling changes of that state
setState((prev: IEmployee) => {
const copy = { ...prev }
copy.contact[name[1]] = value
return copy
})
The problem is that it somehow changes not only the state but also employeesInitialState object that I use just to initially fill the state. That object is in a separate file and is just a constant that I am exporting and for some reason it is getting changed.
1
You’re making a shallow copy and mutating an internal object.
setState((prev: IEmployee) => {
return { ...prev, contact: { ...prev.contact, [name[1]]: value } };
});
to shallowly copy contact
too and only modify the single value from the copied contact
.
In non-React terms:
> foo = {baz: {wah: "quux"}}
{baz: {…}}
> foo2 = {...foo}
{baz: {…}}
> foo2.baz.weh = "wooh"
'wooh'
> foo.baz
{wah: 'quux', weh: 'wooh'} // foo.baz and foo2.baz are the same object so both were modified
There are libraries such as Mutative to make this sort of immutable modification more convenient.
Spread operator cannot clone nested objects or arrays. It only creates copies of the top-level elements(primitive values like number
or string
.
If the IEmployee
is stringifiable you can clone it like this by create a string from the object and then parse it back to form a new one with different ref
setState((prev: IEmployee) => {
const copy = JSON.parse(JSON.stringify(prev));
copy.contact[name[1]] = value
return copy
})
1