Copying Nested Objects: Spread vs. Immer.js

1. Copying with the Spread Operator


const originalObject = {
  name: 'Alice',
  age: 25,
  address: { city: 'Wonderland', zip: 12345 },
};

// Shallow copy using the spread operator
const shallowCopy = {
  ...originalObject,
  address: { ...originalObject.address }, // Nested object needs its own spread
};

// Modify the copied object
shallowCopy.address.city = 'New Wonderland';

The spread operator creates a shallow copy of the original object. For nested objects, you must also spread the nested properties to ensure they are copied correctly. This prevents the original object from being modified.


console.log(originalObject.address.city); // Wonderland
console.log(shallowCopy.address.city); // New Wonderland

2. Copying with Immer.js

Immer.js simplifies state management by allowing you to work with mutable state while keeping the original object unchanged. Here's how it works:


const { produce } = require('immer');

const originalObject = {
  name: 'Alice',
  age: 25,
  address: { city: 'Wonderland', zip: 12345 },
};

// Create a deep copy and modify using Immer.js
const newObject = produce(originalObject, (draft) => {
  draft.address.city = 'New Wonderland';
});

In this example, we use produce to create a draft of the original object. You can directly modify the draft, and Immer.js takes care of creating a new immutable object for you.


console.log(originalObject.address.city); // Wonderland
console.log(newObject.address.city); // New Wonderland

Conclusion

Both the spread operator and Immer.js offer effective ways to copy and manage nested objects in JavaScript. The spread operator requires manual copying of nested properties, while Immer.js allows you to work with drafts in a more intuitive manner, automatically handling immutability.

Choose the method that best fits your needs based on the complexity of your objects and your preference for code readability.