Skip to main content

Computed Trees

Overview

A computed tree reactively derives one tree from other observable state. Unlike an ordinary MobX computed value, the result is attached as a tree property, so it can participate in traversal, contexts, references, and life-cycle hooks. See Properties of computed trees for the exact limitations.

To create a computed tree, decorate a get accessor of a class or data model with the @computedTree decorator:

@model("myApp/M")
class M extends Model({
id: idProp,
title: prop("draft spec"),
done: prop(false),
}) {
@computedTree
get view() {
return new V({
// compute a stable/deterministic ID
id: `${this.id}.view`,
summary: `${this.done ? "DONE" : "TODO"} ${this.title}`,
})
}
}

@model("myApp/V")
class V extends Model({
id: idProp,
summary: prop<string>(),
}) {
@computed
get summaryLength() {
return this.summary.length
}
}

To check whether a node is a regular or computed tree node, use the isComputedTreeNode(node: object): boolean utility function.

note

A computed tree property differs from a regular MobX computed property: it evaluates eagerly, is attached when its model is instantiated, remains cached without an observer, and does not suspend when unobserved. A regular MobX computed value evaluates lazily and, by default, suspends when it is no longer observed.

Properties of computed trees

Computed trees have the following properties:

  • Immutability because a computed tree is derived from another (mutable or computed) tree or observable value. Immutability is enforced at runtime by means of the readonly middleware.
  • Action middlewares are never applied to a computed tree because of its immutability.
  • Contexts are available within a computed tree, across computed trees, and across the boundary between a regular and a computed tree.
  • Tree traversal methods work within a computed tree, across computed trees, and across the boundary between regular and computed trees. Most mutating utility methods do not work on computed tree nodes because they are immutable. onChildAttachedTo is supported, and its listener runs when a computed child is recomputed.
  • References are available within a computed tree, across computed trees, and across the boundary between a regular and a computed tree. When referencing a model instance in a computed tree, it is important that the ID of the referenced model instance is stable across re-computations of the computed tree.
  • Back-references are available within a computed tree, across computed trees, and across the boundary between a regular and a computed tree.
  • Life-cycle event hooks are available and work as expected. onAttachedToRootStore is called upon each re-computation of the computed tree when it is part of a root store tree.
  • Snapshots do not contain data of computed trees.
  • Patches are not generated for computed tree nodes because of immutability.