Search code examples
typescriptmobxts-jest

MobX makeObservable does not work with Jest


I am trying to test my stores with Jest and when I use makeObservable, I get the following error:

[MobX] Cannot apply 'observable' to '[email protected]': Field not found.

      23 |
      24 |   constructor() {
    > 25 |     makeObservable(this, {
         |                   ^
      26 |       todos: observable,
      27 |       filter: observable
      28 |     })

      at die (node_modules/mobx/src/errors.ts:84:15)
      at ObservableObjectAdministration.make_ (node_modules/mobx/src/types/observableobject.ts:250:17)
      at forEach (node_modules/mobx/src/api/makeObservable.ts:37:49)
          at Array.forEach (<anonymous>)
      at makeObservable (node_modules/mobx/src/api/makeObservable.ts:37:30)
      at new TodoStore (src/typings/models/ToDoStore.ts:25:19)
      at tests/looseReplaceNodes.test.ts:76:17
      at step (tests/looseReplaceNodes.test.ts:33:23)
      at Object.next (tests/looseReplaceNodes.test.ts:14:53)
      at tests/looseReplaceNodes.test.ts:8:71

Class in question:

export class TodoStore {
  todos: Todo[]
  filter: string

  constructor() {
    makeObservable(this, {
      todos: observable,
      filter: observable
    })
    this.todos = []
    this.filter = ""
  }
  createTodo(value: any) {
    this.todos.push(new Todo(value))
  }
}

This goes away when I use makeAutoObservable instead but that doesn't work for my use-case (this is a toy example). I don't want to use decorators as MobX seems to be moving away from this.

Any ideas?


Solution

  • The easiest way is to rewrite it like that:

    export class TodoStore {
      todos: Todo[] = []
      filter: string = ""
    
      constructor() {
        makeObservable(this, {
          todos: observable,
          filter: observable
        })
      }
      createTodo(value: any) {
        this.todos.push(new Todo(value))
      }
    }
    

    Or check configuration that you need to apply:

    TypeScript: Set the compiler option "useDefineForClassFields": true.

    Babel: Make sure to use at least version 7.12, with the following configuration:

    {
        "plugins": [["@babel/plugin-proposal-class-properties", { "loose": false }]],
        // Babel >= 7.13.0 (https://babeljs.io/docs/en/assumptions)
        "assumptions": {
            "setPublicClassFields": false
        }
    }
    

    Usually it is better to call make(Auto)Observable as the last thing in constructor, or define properties right away.