mobx: Don't autoconvert function without arguments into getters
For me, one of the least pleasant parts of mobx is automatic converting function without arguments to getters.
The problem
// ordinar mobx store
class KittensStore {
@observable myKittens = [];
addKitten(kitten) {
this.myKittens.push(kitten);
}
}
// somewhere in ui:
kittensStore.addKitten({
name: "Kitty",
sayMeow: asReference(() => alert('meow')), // ui have to know about store internals
// and that the values will be mobxified
sayText: (text) => alert(text), // doesn't need asReference, feels inconcistent
onClick: () => alert('hello'), // damn, I've forgotten about autoconverting
});
Proposition
It would be really nice not to make such a bold assumption. We can introduce special modifier computed, so if one really want to create getter, he can show it explicitly:
extendObservable(this, {
count: 0,
doubleCount: computed(() => this.count * 2),
});
Pros:
- No magic
- More consistent API
- Any data can be accessed the same way after mobxification
- Less surprises for the new developers
- Easy to find and rewrite ‘asGetter’ accordingly (for example, during upgrading to es2015)
Cons:
- Breaking change
PS: I know about asFlat
UPD
changed asGetter -> computed
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 23 (15 by maintainers)
Commits related to this issue
- Added support for setters on computed props, fixes #421, #463 — committed to mobxjs/mobx by mweststrate 8 years ago
- implemented getters for plain objects, see #421 — committed to mobxjs/mobx by mweststrate 8 years ago
- Add warning about automatic computed conversion, see #421 / #532 — committed to mobxjs/mobx by mweststrate 8 years ago
it is wrapped in an action indeed. thanks for the idea btw, despite my initial scepticism I really like it! wish i had realized half a year ago this is valid es5 ☺ I think I’m gonna push this as the idiomatic way to create computeds without decorator
Op wo 31 aug. 2016 22:52 schreef urugator notifications@github.com:
@mweststrate Actual prop descriptor, obtained by
Object.getOwnPropertyDescriptor()Btw I actually never realized this is valid ES5 syntax 😕
Note that the above syntax won’t work afaik, should be
get volume() { ... }which is slightly uglier.But yes, I admit it looks tempting. Was quite easy to setup, see above commit 😃
As @andykog made clear, there is no point in observing a getter field, because it’s “value” can’t be changed in an observable way. So a getter defined in an observable is practically unobservable (or am I missing something?), which seems a bit wierd to me.
Also, I think, it kinda makes sense to turn getter into computed, because getter is in fact a normal field, which value is a just a derivation of other field/s. If those other fields form an observable state of the object, shouldn’t their derivations form an observable state as well? (And note, that we are explicitely marking the getter as observable, by placing it in observable object definition, so one can still create a normal getter)
Similary to: “What if somebody actually wants to create a normal getter”? I could ask: What if somebody actually wants to create a normal function? But that’s not the problem we are dealing with. We don’t want the function to be normal, but observable. The actual question is, observable how? As a reference or something else (computed)? So I think, we should analogically ask in which way the getter should be observable.
And the least importantly, it’s more appealing 😃
EDIT:
In that case I think the following should feel arbitrary as well:
{}meansobservable({})[]meansobservable([])EDIT: fixed getter syntax
@urugator sorry you’re right. On the last question, what do you mean by
getters? Anything that looks like a prop descriptor, or actual property descriptors? That might be convenient for ES6 user indeed@andykog Thought about it, I think the current behavior should indeed be deprecated, as in unexpectly ‘breaks’ the type of an assignment, especially in less obvious cases like: