π Mastering Shallow vs Deep Copy in JavaScript & React β From Scratch to Advanced

βοΈ Introduction
If you've ever wondered why updating an object in React causes unexpected changes elsewhere in your app β youβve likely fallen into the shallow copy trap.
In JavaScript, the way objects and arrays are copied can lead to side effects, bugs, and confusing behavior β especially in React apps where immutability is key.
This blog will take you from zero to advanced in understanding and using shallow and deep copies, with real-world examples, React use cases, and a drag-and-drop state update challenge!
β Step 1: What is Shallow Copy?
A shallow copy duplicates the top-level properties of an object or array. If there are nested objects or arrays, only their references are copied β not their values.
π§ͺ Example:
const original = {
name: "John",
address: { city: "London" },
};
const shallowCopy = { ...original };
shallowCopy.address.city = "Paris";
console.log(original.address.city); // π "Paris"
β Gotcha
Modifying shallowCopy.address.city
also changes original.address.city
β because the address
object is shared by reference.
β Step 2: What is Deep Copy?
A deep copy creates a full copy of an object, including all nested objects/arrays. Changes to the copy wonβt affect the original.
π§ Methods to Create Deep Copy:
structuredClone()
(Modern browsers)JSON.parse(JSON.stringify(...))
(Simple but limited)Libraries like
lodash.cloneDeep()
π‘ Example:
const original = {
name: "John",
address: { city: "London" },
};
// β
Deep copy
const deepCopy = structuredClone(original);
deepCopy.address.city = "Paris";
console.log(original.address.city); // π "London"
βοΈ Real-World React Example: Todo State Update
Letβs say you're managing nested project todos in React.
π§ Why You Need Copying:
React state should not be mutated directly. If you do, React may not detect the change and re-render properly.
β Working Example
const [projects, setProjects] = useState([
{
name: "Work",
todos: [
{ id: 1, task: "Email boss", done: false },
{ id: 2, task: "Finish report", done: true },
],
},
]);
const toggleTask = (projectId, todoId) => {
const updatedProjects = projects.map((proj, idx) =>
idx === projectId
? {
...proj,
todos: proj.todos.map((todo) =>
todo.id === todoId ? { ...todo, done: !todo.done } : todo
),
}
: proj
);
setProjects(updatedProjects);
};
β
Here, weβre making a shallow copy at each level (projects
, proj
, and todo
) to avoid mutating the original state.
π§© Step 3: Drag & Drop Challenge with Nested Deep Updates
Imagine a drag-and-drop interface where you move tasks across projects. You must update deep nested arrays safely!
π§ͺ Sample State Structure
const [projects, setProjects] = useState([
{
name: "Work",
todos: [
{ id: 1, task: "Design UI" },
{ id: 2, task: "Fix bugs" },
],
},
{
name: "Home",
todos: [
{ id: 3, task: "Cook dinner" },
],
},
]);
β Challenge: Move task with ID 2 from "Work" to "Home"
const moveTask = (fromIndex, toIndex, taskId) => {
const clonedProjects = structuredClone(projects);
const fromTodos = clonedProjects[fromIndex].todos;
const toTodos = clonedProjects[toIndex].todos;
const taskToMove = fromTodos.find(todo => todo.id === taskId);
clonedProjects[fromIndex].todos = fromTodos.filter(todo => todo.id !== taskId);
toTodos.push(taskToMove);
setProjects(clonedProjects);
};
β
Here, we use structuredClone()
for a deep copy to safely update without side effects.
π― Step 4: Key Takeaways
π Concept | Shallow Copy | Deep Copy |
Top-Level Props | β Copied | β Copied |
Nested Objects | β Shared (Reference) | β Copied (New References) |
React Usage | β οΈ Can lead to bugs | β Safest for immutability |
Methods | ...spread , Object.assign() | structuredClone() , cloneDeep() |
π Interview Questions to Practice
β What is the difference between shallow and deep copy in JavaScript?
β How do you ensure immutability while updating deeply nested React state?
β How would you implement a deep copy in older browsers?
β What issues can arise if you directly mutate a nested object in React?
π‘ Conclusion
Mastering deep vs. shallow copying will take your JavaScript and React skills to the next level. Itβs essential for state management, working with APIs, and building predictable, maintainable apps.
π Practice with real-world nested objects
βοΈ Always treat state as immutable in React
π§ Know when to use shallow or deep copy!
π Bonus: GitHub & Social Links
π You can try this on CodeSandbox or StackBlitz to see how it works!
If this helped, give it a like or comment. Happy coding! π
Subscribe to my newsletter
Read articles from krishan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

krishan
krishan
π Hey, I'm a Frontend Developer passionate about building clean, user-friendly interfaces. π Learning and sharing everything from React, JavaScript, HTML/CSS to advanced topics like Data Structures, Algorithms & System Design. π» Documenting my journey from fundamentals to becoming a top-tier developer β one blog at a time. π Join me as I break down complex topics into easy, practical lessons β with GitHub repos, code snippets, and real-world examples. π Consistent growth, community learning, and aiming high!