unknown39825

What is mobx

Mobx Learning

MobX Core Concepts

Observable State

What: Data that MobX tracks for changes

import { observable, makeObservable } from 'mobx'

class Store {
  count = 0
  
  constructor() {
    makeObservable(this, {
      count: observable
    })
  }
}

Actions

What: Functions that modify observable state

import { action } from 'mobx'

class Store {
  increment = () => {
    this.count++
  }

  constructor() {
    makeObservable(this, {
      count: observable,
      increment: action
    })
  }
}

Computed Values

What: Derived values that update automatically when dependencies change

import { computed } from 'mobx'

class Store {
  get doubleCount() {
    return this.count * 2
  }

  constructor() {
    makeObservable(this, {
      count: observable,
      doubleCount: computed
    })
  }
}

Reactions

What: Side effects that run when observables change

autorun

Runs immediately and re-runs when dependencies change:

import { autorun } from 'mobx'

autorun(() => {
  console.log(`Count is: ${store.count}`)
})

reaction

Runs only when specific data changes:

import { reaction } from 'mobx'

reaction(
  () => store.count,
  (count) => console.log(count)
)

when

Runs once when condition becomes true:

import { when } from 'mobx'

when(
  () => store.count > 10,
  () => console.log('Count exceeded 10!')
)

Lit Integration

What: Using MobX with Lit web components

import { LitElement, html } from 'lit'
import { customElement, property } from 'lit/decorators.js'
import { autorun } from 'mobx'

@customElement('counter-element')
class CounterElement extends LitElement {
  @property({ type: Number }) count = 0

  connectedCallback() {
    super.connectedCallback()
    this.disposer = autorun(() => {
      this.count = store.count
    })
  }

  disconnectedCallback() {
    super.disconnectedCallback()
    this.disposer?.()
  }

  render() {
    return html`
      <div>
        <p>Count: ${this.count}</p>
        <button @click=${store.increment}>+</button>
      </div>
    `
  }
}

Core Principles

  1. Anything that can be derived, should be derived
    Use computed values instead of storing derived data

  2. State should be minimal
    Only store what cannot be computed from other state

  3. Actions modify state
    All state modifications should happen in actions


Key Decorators & Functions

ConceptPurposeUsage
observableMakes data reactive@observable or observable(obj)
actionMarks state-modifying functions@action or action(fn)
computedCreates derived values@computed get value()
observerMakes Lit components reactiveUse autorun in lifecycle
makeObservableSetup observability in classIn constructor
runInActionExecute code as an actionrunInAction(() => {})

Best Practices

  • Always use makeObservable in constructors for class-based stores
  • Keep actions simple – one responsibility per action
  • Use computed for expensive calculations that depend on observables
  • Minimize observable surface area – only make necessary data observable
  • Use strict mode in development to catch anti-patterns

Mental Model

MobX = Spreadsheet for JavaScript

ConceptAnalogy
ObservablesCells with data
ComputedFormulas that auto-update
ActionsUser inputs that change cells
ReactionsSide effects when cells change

Useful Chrome Extensions


PlantUML Diagram

Loading Diagram...