Lesson 17 +10 XP

State Immutability Rules

State Immutability Rules

In React, state must be treated as immutable (read-only). You should never modify existing state objects or arrays directly.

Why Immutability Matters

React determines whether a component needs to re-render by comparing object memory references (Object.is(oldState, newState)).

If you mutate an existing array or object directly, its memory reference remains identical. React assumes nothing has changed and skips re-rendering.

// ❌ WRONG: Mutating state directly!
const [items, setItems] = useState(['Apple', 'Banana']);

function addItemBad() {
  items.push('Cherry'); // Mutates existing array in memory!
  setItems(items);     // Same reference! React will NOT re-render!
}

// ✅ CORRECT: Creating a new copy using ES6 spread operator (...)
function addItemGood() {
  setItems([...items, 'Cherry']); // New array reference created!
}

Updating Arrays Immutably

Operation❌ Mutable Method (Avoid)✅ Immutable Alternative
Add itemarr.push(item)[...arr, item]
Prepend itemarr.unshift(item)[item, ...arr]
Remove itemarr.splice(index, 1)arr.filter(item => ...)
Modify itemarr[index] = valarr.map(item => ...)
Sort arrayarr.sort()[...arr].sort()
// Example: Removing an item immutably with filter
function TodoList() {
  const [todos, setTodos] = useState([
    { id: 1, text: "Buy groceries" },
    { id: 2, text: "Walk dog" }
  ]);

  const deleteTodo = (idToDelete) => {
    setTodos(todos.filter(todo => todo.id !== idToDelete));
  };

  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>
          {todo.text}
          <button onClick={() => deleteTodo(todo.id)}>Delete</button>
        </li>
      ))}
    </ul>
  );
}

Summary & TL;DR

  • Always treat React state as immutable.
  • Never use mutating methods like push(), pop(), splice(), or direct assignment on state.
  • Create new copies of arrays and objects using spread syntax (...), filter(), and map().