Frontend Patterns

Pattern

Immutable Update

Treat state as immutable and create new copies when making changes for predictability.

State Management Intermediate

Immutable Update

Problem

Directly mutating state objects breaks change detection, causing components to show stale data. Array.push() or object property assignments don’t trigger re-renders. Debugging becomes impossible when state changes happen without clear tracking. Time-travel debugging and undo/redo features can’t work because there’s no history of immutable states.

Solution

Create new objects rather than modifying existing ones when updating state. This enables reliable change detection and prevents subtle bugs from shared mutable references.

Example

This example demonstrates creating new copies of state instead of mutating existing objects to enable reliable change detection.

// Immutable array update: Create new array with spread, don't use push()
setState(prev => [...prev, newItem]);

// Immutable object update: Create new object with spread, don't modify properties directly
setState(prev => ({ ...prev, name: 'New Name' }));

Benefits

  • Enables reliable change detection since reference equality checks can detect updates.
  • Prevents bugs from shared mutable references between components or functions.
  • Makes debugging easier by maintaining a history of immutable state snapshots.
  • Supports advanced features like time-travel debugging and undo/redo.

Tradeoffs

  • Requires creating new objects for every update, adding memory and performance overhead.
  • Can be verbose with nested updates requiring deep spreads or library helpers.
  • Performance degrades with large data structures that get copied frequently.
  • Learning curve for developers used to direct mutation patterns.
Stay Updated

Get New Patterns
in Your Inbox

Join thousands of developers receiving weekly insights on frontend architecture patterns

No spam. Unsubscribe anytime.