class OrderLine {
@tracked price = 0
@tracked amount = 1
get total() {
return this.price * this.amount
}
}
This is more important than it looks. The fact that you don't need to decorate the getter also means that you can break up a computation that uses tracked properties into smaller functions without needing to think about how the smaller pieces should be written. You just use functions.
Here's what happens when you try to add methods with arguments to MobX:
import { observable } from "mobx"
import { computedFn } from "mobx-utils"
class Todos {
@observable todos = []
getAllTodosByUser = computedFn(function getAllTodosByUser(userId) {
return this.todos.filter(todo => todo.user === userId))
})
}
And Octane:
import { tracked } from "@glimmer/tracking";
class Todos {
@tracked todos = [];
getAllTodosByUser(userId) {
return this.todos.filter(todo => todo.user === userId))
}
}
The rule in Octane is: "mark any reactive property as @tracked, and use normal JavaScript for derived properties". That's pretty cool!
After trying out almost most of the major libraries in the frontend ecosystem I feel that MobX-style observables (in combination with a state-tree abstraction like MST) simply offer the best combination of developer experience and performance.
It is not hard to write readable code with hooks (and hook based state management solutions), but it takes a lot more ramp up time and I see junior members in our team struggle with the nuances around closures (what value was captured when in the component lifecycle) frequently. Adopting MobX has been a huge productivity boost for our team.
At the same time, I feel the full potential of MobX is not fully realized in react ecosystem because the React core team does not recommend Object oriented state management with observables - the ecosystem would be so much better if popular components accepted observable data-structures and were built with implicit change tracking in mind (rather than the usual combination of controlled+uncontrolled props and callbacks which ends up being verbose and repetitive).
I hope octane results in Ember gaining traction in the community. It would be nice to have a framework that embraces reactive observable models, without also resorting to weird monkey patching (angular zones).
The underlying implementation is the largest difference. Where MobX relies on pub/sub and observables to propagate dirty state, Glimmer’s autotracking uses a lazy system that incurs minimal cost until render occurs. We’ve found the overall performance of this system to be much better, and the primitive easier to optimize.
And on top of that, the fact that we use a simple reactivity primitive under the hood[1][2] means that we have been able to transition from an API designed for 2012-era two-way bindings to a unidirectional data-flow model with minimal disruption, and with free interoperability between code written with the two APIs (even in the same object).
This also means that we can design new functionality (like Octane's modifiers, and other upcoming reactive APIs) without worrying about how the parts of the system will work together.