MobX-state-tree

MobX-state-tree

  • Documentation
  • TypeDocs
  • Sponsor
  • GitHub

›Basic Concepts

Introduction

  • Welcome to MobX-State-Tree!
  • Installation
  • Getting Started Tutorial
  • Examples
  • Overview & Philosophy

Basic Concepts

  • Types, models, trees & state
  • Actions
  • Derived values
  • React and MST
  • Snapshots
  • Identifiers and references
  • Asynchronous actions

Advanced Concepts

  • Patches
  • Listening to changes
  • Dependency Injection
  • Middleware
  • Reconciliation
  • Volatile state

API Overview

  • Types overview
  • API overview
  • Lifecycle hooks overview

Tips

  • Talks & Blogs
  • Frequently Asked Questions
  • TypeScript and MST
  • Circular dependencies
  • Simulating inheritance
  • Using snapshots as values
  • Miscellaneous Tips

Compare

  • React Context vs. MobX-State-Tree

Recipes

  • Auto-Generated Property Setter Actions
  • Pre-built Form Types with MST Form Type
  • Manage Asynchronous Data with mst-query
Edit

Actions

egghead.io lesson 2: Attach Behavior to mobx-state-tree Models Using Actions
Hosted on egghead.io

By default, nodes can only be modified by one of their actions, or by actions higher up in the tree. Actions can be defined by returning an object from the action initializer function that was passed to actions. The initializer function is executed for each instance, so that self is always bound to the current instance. Also, the closure of that function can be used to store so called volatile state for the instance or to create private functions that can only be invoked from the actions, but not from the outside.

const Todo = types
    .model({
        title: types.string
    })
    .actions(self => {
        function setTitle(newTitle) {
            self.title = newTitle
        }

        return {
            setTitle
        }
    })

Shorter form if no local state or private functions are involved:

const Todo = types
    .model({
        title: types.string
    })
    .actions(self => ({
        // note the `({`, we are returning an object literal
        setTitle(newTitle) {
            self.title = newTitle
        }
    }))

Actions are replayable and are therefore constrained in several ways:

  • Trying to modify a node without using an action will throw an exception.
  • It's recommended to make sure action arguments are serializable. Some arguments can be serialized automatically such as relative paths to other nodes
  • Actions can only modify models that belong to the (sub)tree on which they are invoked
  • You cannot use this inside actions. Instead, use self. This makes it safe to pass actions around without binding them or wrapping them in arrow functions.

Useful methods:

  • onAction listens to any action that is invoked on the model or any of its descendants.
  • addMiddleware adds an interceptor function to any action invoked on the subtree.
  • applyAction invokes an action on the model according to the given action description

Action listeners versus middleware

The difference between action listeners and middleware is: middleware can intercept the action that is about to be invoked, modify arguments, return types, etc. Action listeners cannot intercept and are only notified. Action listeners receive the action arguments in a serializable format, while middleware receives the raw arguments. (onAction is actually just a built-in middleware).

For more details on creating middleware, see the docs.

Disabling protected mode

This may be desired if the default protection of mobx-state-tree doesn't fit your use case. For example, if you are not interested in replayable actions or hate the effort of writing actions to modify any field, unprotect(tree) will disable the protected mode of a tree allowing anyone to directly modify the tree.

← Types, models, trees & stateDerived values →
MobX-state-tree
Docs
Getting StartedBasic conceptsAdvanced conceptsAPI Reference
Community
GitHub DiscussionsStack Overflow
More
BlogGitHubStar
Facebook Open Source
Copyright © 2025 Michel Weststrate