乐闻世界logo
搜索文章和话题

What are the differences between observable, computed, and action in MobX?

2月19日 17:57

In MobX, observable, computed, and action are three core concepts, each with different purposes and characteristics:

Observable

Purpose:

  • Create trackable state
  • Notify all observers that depend on it when state changes

Usage:

javascript
import { observable } from 'mobx'; class Store { @observable count = 0; @observable user = { name: 'John', age: 30 }; @observable items = []; } // Or using functional API const store = observable({ count: 0, user: { name: 'John', age: 30 }, items: [] });

Characteristics:

  • Can decorate class properties or create observable objects
  • Supports objects, arrays, Maps, Sets, and other data structures
  • Deeply observable: nested objects also become observable automatically
  • In MobX 6, uses decorator API by default or makeObservable

Computed

Purpose:

  • Create derived values that are automatically calculated based on other observable states
  • Has caching mechanism, only recalculates when dependencies change
  • Avoids repeated calculations, improves performance

Usage:

javascript
import { observable, computed } from 'mobx'; class Store { @observable firstName = 'John'; @observable lastName = 'Doe'; @computed get fullName() { return `${this.firstName} ${this.lastName}`; } } // Or using functional API const store = observable({ firstName: 'John', lastName: 'Doe' }); const fullName = computed(() => `${store.firstName} ${store.lastName}`);

Characteristics:

  • Read-only property (by default)
  • Automatically caches calculation results
  • Only recalculates when dependent observables change
  • Can be used by other computed values or observers
  • Lazy calculation: only calculates when accessed

Action

Purpose:

  • Encapsulate state modification logic
  • Ensure state modifications are trackable and predictable
  • In MobX 6, all state modifications must be done within actions

Usage:

javascript
import { observable, action } from 'mobx'; class Store { @observable count = 0; @action increment() { this.count++; } @action.bound decrement = () => { this.count--; }; @action async fetchData() { this.loading = true; const data = await api.getData(); this.data = data; this.loading = false; } } // Or using functional API const store = observable({ count: 0 }); store.increment = action(() => { store.count++; });

Characteristics:

  • Mandatory in MobX 6
  • Can be synchronous or asynchronous
  • action.bound automatically binds this
  • Can be nested
  • Provides better debugging experience and predictability

Relationship Between the Three

  1. Observable is the foundation, providing observable state
  2. Computed depends on observables, automatically calculating derived values
  3. Action is used to modify observables, triggering dependency updates

Best Practices

  1. Using observable:

    • Only use observable for state that needs to be tracked
    • Avoid using observable for entire application state
    • Use makeAutoObservable for automatic inference
  2. Using computed:

    • Use for calculating derived values, not in components
    • Avoid side effects in computed values
    • Use computed for complex calculation logic
  3. Using action:

    • All state modifications should be done within actions
    • Async operations should also be wrapped in actions
    • Use action.bound to avoid binding issues

Performance Considerations

  • Observable itself doesn't bring performance overhead
  • Computed improves performance through caching mechanism
  • Action helps batch updates, reducing unnecessary re-renders

Understanding the differences between these three concepts and using them correctly is key to mastering MobX.

标签:Mobx