You already know you're not supposed to mutate state directly when you update the state in React.

However, what if one of the members of the object you're updating is a reference?

Do you have to create a new version of that object/array as well?

const [order, setOrder] = useState({ 
  id: '12345',
  customer: 'John Doe',
  tags: ['black', 'day-trip'],	// <-- this is a reference!
  shippingAddress: {			// <-- this is also a reference
    street: 'Steiner St. 27',
    city: 'San Francisco'
  }
})

You don't need to deep clone when mutating state

If you only need to change one of the basic props of your object, it's ok to leave everything else the same - i.e. shallow copy the other properties that are nested.

const newOrder = { ...order, name: 'John Doe The Second'}

... unless the nested property actually changed

But what if something inside the nested reference changes? Then indeed, you would  need to deep clone that:

// Let's add a new tag
const newOrder = { 
  ...order, 
  tags: [
    ...order.tags, 
    'some-new-tag'
  ]
};

// .. or update the shipping address
const newOrder = { 
  ...order, 
  shippingAddress: { 
    ...order.shippingAddress, 
    city: 'New York'
}}

But why is it that you don't need to deep clone?

You've seen that it's enough to do shallow copies of nested properties if they haven't changed .. but why?

It all boils down to why you create copies in the first place - to let React know that your state changed so it can rerender. If you also create new references for nested props as well, React will assume those changed as well, and rerender them!

So if you had a component showing the list of tags or the shipping address, and you would deep copy those when updating the state, React would re-render them even if they hadn't changed, just because a new reference was passed!

Further reading

I hope you found this useful! If you want to learn more about how references work and immutably changing state, make sure to check out these links as well: