skip to Main Content

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.

2

Answers


  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.

    Login or Signup to reply.
  2. 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
      })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search