Search code examples
javascripttypescriptobservablemobx

How can I get autorun to work with runInAction, using mobx?


Trying to learn mobx and runInAction, but struggling to understand why autorun is not invoking my callback in the following example:

class FooClass {

    // constructor() {
    //     this.fooMethod();
    // }

    @observable myBool = false;

    async fooMethod() {

        await new Promise(r => setTimeout(r, 1000));
        runInAction(() => this.myBool = true); // <--- myBool: true is never logged to the console. why?
        await new Promise(r => setTimeout(r, 3000));
        runInAction(() => this.myBool = false); // <--- also not logged
    }
}

let foo = new FooClass();

foo.fooMethod();
autorun(() => console.log("myBool:", foo.myBool));

Using TypeScript and babel with decorators.

As I understand it, runInAction(...) can be used if you want to change some observables when you are not inside a method which is marked as an action?

Why is my script not working?


Solution

  • You are probably using MobX v6 and its api changed a little bit, you now need to add makeAutoObservable or makeObservable call inside constructor, like that:

    import { autorun, makeAutoObservable, observable, runInAction } from 'mobx';
    
    class FooClass {
      constructor() {
        makeAutoObservable(this);
    
        autorun(() => console.log('myBool:', this.myBool));
        this.fooMethod();
      }
    
      // You can actually remove decorator here if you use `makeAutoObservable`
      @observable myBool = false;
    
      async fooMethod() {
        await new Promise((r) => setTimeout(r, 1000));
        runInAction(() => (this.myBool = true)); // it will be logged now
        await new Promise((r) => setTimeout(r, 3000));
        runInAction(() => (this.myBool = false)); // it will be logged now too
      }
    }
    
    new FooClass();
    

    Codesandbox

    More info in the docs