Does React make a clone of your object when you use the set function?

I’m trying to avoid modifying state directly, so I am using lodash cloneDeep() and then setting state using the clone. However, I want to make additional changes (after an async request) and set state again. After I and pass my clone to the set function, is it off limits to continue making changes to that clone? Do I need to re-clone my clone to be safe, or does React make a clone of my clone? The code may help explain the issue:

const [user, setUser] = useState({ name: '', email: '' })

const newUser = cloneDeep(user) // cloning to avoid modifying state directly
newUser.name = 'Steve' // setting a property on the clone
setUser(newUser) // all good up to this point

// some async stuff happens, then later:

newUser.email = 'steve@example.com' // still modifying the clone, but is this safe?
setUser(newUser)

Since I modified the clone that I previously passed with setUser did that just modify state directly?

I tried to inspect the React source code to determine if they were making a clone when I called setUser() but I couldn’t comprehend what was going on. 🙂

Answer

newUser.email = 'steve@example.com' // still modifying the clone, but is this safe?
setUser(newUser)

I don’t think this is a good idea. newUser is the same reference that you used in the previous call to setUser (before async request), so react may actually bail out of this setState because it is same as the value which you used during previous call to setState.

Also your situation is same as this

let user = {};
setUser(user);
user.a=1;

in the following sense: once I pass user to setUser on step 2, it doesn’t matter whether it is brand new object or something that I cloned before, the point is on step 3 I am modifying something I passed to setUser in step 2. And this does look to me like modifying something which is in state.


So try to update state in immutable way the second time too. Most of the time doing immutable state updates with shallow copy using ... has worked for me (if you do it right), so you could avoid extra library.