Mobx: function-properties in observable objects are not enumerable

Created on 19 Nov 2020  路  4Comments  路  Source: mobxjs/mobx

Intended outcome:

function-properties in observable objects are expected to be enumerable

Actual outcome:

function-properties are gone when iterating an observable object

How to reproduce the issue:

I created this example: https://codesandbox.io/s/jovial-black-rq0pw?file=/src/index.ts

The onMore-prop is actually not contained when calling Object.keys(x.notification) since functions are not enumerable in observable objects. I am coming from mobx 4 and this used to work and now it breaks my app in some cases, since I use spreading to pass observable-objects to components like <Component {...notification} />

Versions

Mobx 6

has PR 馃巵 mobx 馃憮 needs investigation

All 4 comments

We may change it so that enumerability is respected, but I can't give you a promise atm, it's being discussed/worked on.
Related #2586

For the time being as a workaround try:

const obj = {
      text: "abc",
      onMore: action(() => {})
};

Or

const obj = observable({
      text: "abc",
      onMore: () => {},
}, {
  onMore: false
});

Please note that spreading observable objects into components as props is an anti pattern: https://mobx.js.org/react-integration.html#tip-grab-values-from-objects-as-late-as-possible. The idiomatic way to pass the notification down is <Component notification={notification} />, while making sure <Component> is an observer.

If you can't make Component observer because it is not under your control, I recommend pass down properties down explicitly. Especially with actions you probably want to do that anyway to make sure callbacks are invoked by with the right context (<Component title={notification.title} onSetTitle={(title) => notication.onSetTitle(title)} /> rather than <Component {...notification} /> which will break if notification.onSetTitle wasn't bound)

It seems very unexpected that properties may suddenly be removed from an object when enumerating, especially since imo mobx' power has always been that it makes you interact with the observables like they are native object/maps/arrays etc (with a little magic when you wrap them into observers).

I can see how it is an anti-pattern but I've been using it mostly in tests and stories to quickly create a set of observable values that I then spread into a react component. When I upgraded to MobX 6 many of these stories broke. There might be tons of more use-cases but I think most important is that its just very DX unfriendly .

Was this page helpful?
0 / 5 - 0 ratings