Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

class overrides problem #600

Closed
HaveF opened this issue Oct 8, 2016 · 7 comments
Closed

class overrides problem #600

HaveF opened this issue Oct 8, 2016 · 7 comments

Comments

@HaveF
Copy link

HaveF commented Oct 8, 2016

case 1 JS Bin

mobx@2.4.3

const {observable, computed, extendObservable} = mobx;

class BaseClass {
  constructor(baseProp = 1) {
    extendObservable(this, {
      baseProp: baseProp,
                get toJson() {
                  return {baseProp: this.baseProp}
                }
    })
  }


}

class ChildClass extends BaseClass {
  constructor(prop=2) {
    super(prop)
    extendObservable(this, {
      color: 'black',
             get toJson() {
               return {
                 baseProp: this.baseProp,
                 color:    this.color
               }
             }
    })
  }
}

var base = new BaseClass(11);
console.log(base.toJson)


var child = new ChildClass(22);
console.log(child.toJson)

the result is:

[object Object] {
baseProp: 11
}
[object Object] {
baseProp: undefined,
color: "black"
}

but I do like to see this result:

[object Object] {
baseProp: 11
}
[object Object] {
baseProp: 22,
color: "black"
}

case 2 JS Bin

same code, but with mobx@2.6.0, the result is

[object Object] {
baseProp: 11
}
"error"
"Error: [mobx] Invariant failed: cannot redefine property toJson
at invariant (https://npmcdn.com/mobx@2.6.0/lib/mobx.umd.js:2579:15)
at setObservableObjectInstanceProperty (https://npmcdn.com/mobx@2.6.0/lib/mobx.umd.js:2177:9)
at extendObservableHelper (https://npmcdn.com/mobx@2.6.0/lib/mobx.umd.js:335:13)
at https://npmcdn.com/mobx@2.6.0/lib/mobx.umd.js:323:9
at Array.forEach (native)
at extendObservable (https://npmcdn.com/mobx@2.6.0/lib/mobx.umd.js:320:16)
at new ChildClass (zekadedita.js:19:5)
at zekadedita.js:35:13"

case 3 JS Bin

use @observable and mobx@2.6.0

const {observable, computed} = mobx;

class BaseClass {
  @observable baseProp = 1;

  constructor(baseProp){
    this.baseProp = baseProp
  }

  @computed get toJson() {
    return {baseProp: this.baseProp}
  }
}

class ChildClass extends BaseClass {
  @observable color = 'black'

  constructor(baseProp){
    super(baseProp)
  }

  @computed get toJson() {
    return {baseProp: this.baseProp, color: this.color}
  }
}

var base = new BaseClass(11);
console.log(base.toJson)


var child = new ChildClass(22);
console.log(child.toJson)

it works! why? I really sucked about no decorators way....but...

[object Object] {
baseProp: 11
}
[object Object] {
baseProp: 22,
color: "black"
}

@mweststrate
Copy link
Member

Note that overriding properties is in principle not supported. If you want to have a inherited toJson mechanism I recommend to declare it only once, in the base class, and then invoke a helper function from there that can do the required super calls. That being said I think that at least the extendObservable based redefinition should work or give a better error.

@HaveF
Copy link
Author

HaveF commented Oct 10, 2016

Thanks for your comments, but I do not know how to write the helper function, define a new toJson method but inherited baseProp properties in ChildClass with extendObservable (case 1).

could you give me more tips? thanks!

btw, in large application, how do you handle class extends problem? I do like to have a base store, and inherit it to get another store.

@urugator
Copy link
Collaborator

urugator commented Oct 10, 2016

class BaseClass {
  constructor(baseProp = 1) {
    extendObservable(this, {
      baseProp: baseProp,
      // observable, not overridable
      get toJson() {
        return this.toJsonHelper;
      }
    });
  }
  // not observable, overridable
  get toJsonHelper() {
    return {baseProp: this.baseProp};
  }

}

class ChildClass extends BaseClass {
  constructor(prop=2) {
    super(prop);
    extendObservable(this, {
      color: 'black',
    });
  }
  // override helper
  get toJsonHelper() {
    return {
      baseProp: this.baseProp,
      color:    this.color
    };
  }
}

Btw I don't think it's mentioned anywhere in doc...

@HaveF
Copy link
Author

HaveF commented Oct 11, 2016

@urugator Thanks! It works.

Anyway, I suppose the extendObservable and @observable way should behave the same,

@mweststrate
Copy link
Member

I think this issue is not common enough to justify further investigation. Overriding fields is a bad idea in most programming languages, and so it is in this case :)

@y-nk
Copy link

y-nk commented Nov 17, 2020

hello 2017 ! i'm hitting similar issue 3 years after. i know mobx5 is discontinued, but i'm only looking for clues on how to solve it (not produce a clean fix).

Following code works with babel6/mobx4, but breaks in babel7/mobx5:

class Model {
  static Schema = {}

  constructor(data) {
    const schema = this.constructor.Schema

    const observables = Object.fromEntries(
      Object.keys(schema).map(key => ([key, this[key]]))
    )

    extendObservable(this, observables)
    this.update(data)
  }

  @action.bound update(data) {
    set(this, data)
  }
}

class User extends Model {
  static Schema = {
    userId: joi.string()
  }

  userId: string
}

const user = new User({ userId: 'foo' })
console.log(user.userId) // undefined

If I comment the prop definition of userId: string, then the code works.
@mweststrate if you have 5mns to look at it, i'd be grateful 🙏

@danielkcz
Copy link
Contributor

danielkcz commented Nov 17, 2020

@y-nk Please, rather than commenting on super old and closed issues, open a new discussion so other people can see it. Obviously, your issue is not the same, otherwise, you would have found your answer above.

Also note that MobX 4/5 is not supported anymore, so consider upgrading to V6 first.

@mobxjs mobxjs locked as resolved and limited conversation to collaborators Nov 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants