Hello, Code Chefs! đ¨âđł
Raise your hand if youâve experienced this horror story:
You have a list state (array), you try to add a new item using .push(). But⌠nothing happens on the screen. Even though console.log shows the data is there.
Is React broken? Nope. Whatâs wrong is how we treat the State.
In React, there is one golden rule: NEVER mutate state directly.
Today, weâre going to cook up the correct way to manipulate arrays in React state. Grab your coffee, letâs get cooking! â
Why push() and splice() are Forbidden
Look at this ânaughtyâ code:
const [todos, setTodos] = useState(["Learn React", "Drink Coffee"]);
const addTodo = () => {
// â WRONG!
todos.push("Take a nap");
setTodos(todos);
};
Why doesnât this work?
Because .push() modifies the array in place (mutating). The memory reference of the array doesnât change.
React is smart but lazy. It checks: âIs the new array reference different from the old one?â
If the reference is the same, React says: âMeh, data looks the same. No need to re-render.â
Thatâs why we must always create a new array whenever we update the state.
1. Adding Data (Add)
Use the Spread Operator (...). This is the easiest way to copy the old array into a new one.
const addTodo = (newTodo) => {
// â
CORRECT!
// We create a new array: [...oldData, newData]
setTodos([...todos, newTodo]);
};
Want to add it to the front (unshift)? Just flip it:
setTodos([newTodo, ...todos]);
2. Removing Data (Delete)
Donât use .splice()! Itâs messy and mutating.
Use the .filter() method.
The concept: âKeep all items EXCEPT the one we want to remove.â
const deleteTodo = (indexToRemove) => {
// â
CORRECT!
setTodos(todos.filter((_, index) => index !== indexToRemove));
};
// Or using ID (recommended)
const deleteById = (id) => {
setTodos(todos.filter((todo) => todo.id !== id));
};
3. Updating Data (Edit)
What if we want to change the status from âIncompleteâ to âCompleteâ?
Donât access the index directly like todos[0].status = "Complete". Thatâs mutating!
Use the .map() method.
The concept: âLoop through all items. If it matches the one we want, change it. If not, leave it alone.â
const toggleStatus = (id) => {
// â
CORRECT!
setTodos(
todos.map((todo) => {
if (todo.id === id) {
// Copy old object, then overwrite 'completed' property
return { ...todo, completed: !todo.completed };
}
// Leave other items alone
return todo;
})
);
};
The Cheat Sheet
| Operation | Forbidden (Mutating) | Recommended (Immutable) |
|---|---|---|
| Add | push(), unshift() | [...arr, item] |
| Remove | pop(), splice() | .filter() |
| Edit | arr[i] = x | .map() |
| Sort | sort(), reverse() | [...arr].sort() (Copy first!) |
Final Thoughts
Manipulating arrays immutably (without changing the original) might feel weird at first, especially if youâre used to standard algorithmic coding. But trust me, this is the key to keeping your React app bug-free and performant.
Bottom line: Always make a fresh copy, donât touch the old one.
Hope this helps! If youâre still confused, letâs grab another coffee. â
Happy Coding! đ