Nadav the Gahbon
Nadav the Gahbon

Reputation: 31

disposing mobx @computed reactions

In the following article it says that reactions of mobx should be disposed: https://mobxjs.github.io/mobx/best/pitfalls.html

Properties that are marked with @computed decorators are a kind of reactions, so it seems that they need to be disposed too. The problem is that unlike an explicit call to autorun(), observe() or other reactions, which return a disposer function, the @computed decorator does not seem to enable us to dispose that reaction.

So the question is - how reactions defined by the @computed decorator should be disposed?

The problem of not disposing might manifest in the following example

export class Observed {
    @observable
    public x: number;
}

export class Observer {

   constructor(private member: Observed){
   }

   @computed
   get doubled(){
      return this.member.x*2;
   }
}

let member = new Observed();
let observer = new Observer(member);

// now pass observer as a model to some react component and use its doubled property

As long as 'member' is alive, observer will be kept alive, unless the reaction that wraps doubled() would be disposed. Even if we add a dispose() function to Observer and call it ourselves, I don't understand how we can access the underlying reaction of doubled() to dispose it.

Upvotes: 2

Views: 5080

Answers (1)

mweststrate
mweststrate

Reputation: 4978

Computed values are automatically disposed (and even reinstantiated when needed) by MobX. MobX can do this because they are supposed to have no side effects. So whenever MobX determines no observers are interested in the computed value anymore, they will be suspended automatically, unsubsubscribing from any observables the computed might use itself. At this point it could be GC-ed (for example because the owning object runs out of scope), or reactivate because a new observer registers.

In other words, in your example Observer will not be kept alive (nor will it be observing Observed) and it can safely be GC-ed. It would be kept alive only if you would use it (indirectly) in a reaction somewhhere, like

const disposer = reaction(() => observer.double, x => console.log(x))

Upvotes: 5

Related Questions