# Suspending mobx computation
# Summary
With mobx (opens new window) you can reevaluate expressions automatically when objects that
those expressions use change.
This is mobx's special sauce and what makes us love it, but sometimes
you want to suspend evaluations until something happens.
The usual way to do it with mobx is by subscribing/unsubscribing to changes, but that means
you have to manage these kind of state synchronization manually.
Instead we can leverage mobx itself to create a new decorator that can suspend evaluations
based on a provided variable.
# Background
In a recent project I was making a react-native app that was working constantly in the background
to process bluetooth events. When the app was in the background we didn't want
to render anything to not overuse the battery.
We were using mobx extensively to drive the logic and views of the app and
didn't want to step outside it to manually manage what observers are allowed to run where.
What we really want is the ability to suspend a mobx computation or reaction based on another observable.
# Building your own computed decorator
We can build our own @computed
decorator that lets us suspend computations arbitrarily:
import { computed} from 'mobx'
const suspended = observable.box(false)
export function setSuspended(value) {
suspended.set(value)
}
export function suspendableComputed(
instance: any,
propertyName: PropertyKey,
descriptor: PropertyDescriptor,
...args
) {
let cached
const oldDescriptor = descriptor.get
descriptor.get = function() {
if (!suspended.get()) {
cached = oldDescriptor.apply(this)
}
return cached
}
return computed(instance, propertyName, descriptor, ...args)
}
so instead of @computed you use suspendableComputed and whenever you
want to suspend all computation you simply call setSuspended(true)
and
anything calling the computed function will get a cached value.
When you want to start evaluating again, you call setSuspended(false)
and the last change that should have triggered your computed evaluation is
triggered again.
# Alternatives
# Subscribing and unsubscribing on events
The usual way of handling such things is simply to stop observing values when you want to suspend evaluation. mobx-react does it automatically when a component is no longer rendered, but it can also be done manually.
# Prioritized render
If the reason why you want to stop computation is because there are some things that have a high priority to be shown right now and other computations might cause lag, and if you are using react, than you can use the new fiber architecture to give your different renders priority.
Though it's still not a finished api, it's likely to be completed and release very soon. For more information you can look at the wonderful example here (opens new window)
# A Library
While we were talking about @computed suspending reactions is also possible
with a similar setup, though it's a bit more complicated.
So for that case I've made a small library that adds suspension to both
computed and reaction in mobx - mobx-suspend (opens new window)