MobX-state-tree

MobX-state-tree

  • Documentation
  • TypeDocs
  • Sponsor
  • GitHub

›Tips

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

Using snapshots as values

Everywhere where you can modify your state tree and assign a model instance, you can also just assign a snapshot, and MST will convert it to a model instance for you. However, that is simply not expressible in static type systems atm (as the type written to a value differs to the type read from it). As a workaround MST offers a cast function, which will try to fool the typesystem into thinking that an snapshot type (and instance as well) is of the related instance type.

const Task = types.model({
    done: false
})
const Store = types.model({
    tasks: types.array(Task),
    selection: types.maybe(Task)
})

const s = Store.create({ tasks: [] })
// `{}` is a valid snapshot of Task, and hence a valid task, MST allows this, but TS doesn't, so we need to use 'cast'
s.tasks.push(cast({}))
s.selection = cast({})

Additionally, for function parameters, MST offers a SnapshotOrInstance<T> type, where T can either be a typeof TYPE or a typeof VARIABLE. In both cases it will resolve to the union of the input (creation) snapshot and instance type of that TYPE or VARIABLE.

Using both at the same time we can express property assignation of complex properties in this form:

const Task = types.model({
    done: false
})
const Store = types
    .model({
        tasks: types.array(Task)
    })
    .actions(self => ({
        addTask(task: SnapshotOrInstance<typeof Task>) {
            self.tasks.push(cast(task))
        },
        replaceTasks(tasks: SnapshotOrInstance<typeof self.tasks>) {
            self.tasks = cast(tasks)
        }
    }))

const s = Store.create({ tasks: [] })

s.addTask({})
// or
s.addTask(Task.create({}))

s.replaceTasks([{ done: true }])
// or
s.replaceTasks(types.array(Task).create([{ done: true }]))

Additionally, the castToSnapshot function can be also used in the inverse case, this is when you want to use an instance inside an snapshot. In this case MST will internally convert the instance to a snapshot before using it, but we need once more to fool TypeScript into thinking that this instance is actually a snapshot.

const task = Task.create({ done: true })
const Store = types.model({
    tasks: types.array(Task)
})

// we cast the task instance to a snapshot so it can be used as part of another snapshot without typing errors
const s = Store.create({ tasks: [castToSnapshot(task)] })

Finally, the castToReferenceSnapshot can be used when we want to use an instance to actually use a reference snapshot (a string or number). In this case MST will internally convert the instance to a reference snapshot before using it, but we need once more to fool TypeScript into thinking that this instance is actually a snapshot of a reference.

const task = Task.create({ id: types.identifier, done: true })
const Store = types.model({
    tasks: types.array(types.reference(Task))
})

// we cast the task instance to a reference snapshot so it can be used as part of another snapshot without typing errors
const s = Store.create({ tasks: [castToReferenceSnapshot(task)] })
← Simulating inheritanceMiscellaneous Tips →
MobX-state-tree
Docs
Getting StartedBasic conceptsAdvanced conceptsAPI Reference
Community
GitHub DiscussionsStack Overflow
More
BlogGitHubStar
Facebook Open Source
Copyright © 2025 Michel Weststrate