Search code examples
javascriptecmascript-6mobxsetteres6-class

Make setter an action using Mobx makeObservable in presence of getter


In mobx if I want to use interheritance I need to use makeObservable rather than makeAutoObservable. But using makeObservable requires I name the actions that mutate state so how can I declare a setter to be an action given it has the same name as the getter?

In other words what goes where I wrote SETTER_FOR_MYVAR or what is another way to achieve the same effect?

class BaseClass {
  _myvar = null

  set myvar(val) {
    this._myvar = val;
  }

  get myvar() {
    return this._myvar;
  }

  other_action() {
    this._myvar = 5;
  }

  constructor() {
    makeObservable(this, {
      _myvar: observable,
      other_action: action,
      SETTER_FOR_MYVAR: action
    });
  }
}

Yes, I know I could farm it out to yet another helper function _myvar_setter and declare that an action but that seems ugly and I'm hoping there is a better way.


Solution

  • Just mark myvar as computed, everything should work out of the box (If I understand correctly what you want):

      constructor() {
        makeObservable(this, {
          _myvar: observable,
          myvar: computed,
          other_action: action
        });
      }
    

    Codesandbox

    Excerpt from the docs:

    It is possible to define a setter for computed values as well. Note that these setters cannot be used to alter the value of the computed property directly, but they can be used as an "inverse" of the derivation. Setters are automatically marked as actions.

    Example:

    class Dimension {
        length = 2
    
        constructor() {
            makeAutoObservable(this)
        }
    
        get squared() {
            return this.length * this.length
        }
        set squared(value) {
            this.length = Math.sqrt(value)
        }
    }
    

    More info in the docs