Mobx-state-tree: safeReference causes "Computed values are not allowed to cause side effects" error

Created on 18 May 2019  路  3Comments  路  Source: mobxjs/mobx-state-tree

_Bug report_

  • [x] I've checked documentation and searched for existing issues
  • [x] I've made sure my project is based on the latest MST version
  • [x] Fork this code sandbox or another minimal reproduction.

Sandbox link or minimal reproduction code

https://codesandbox.io/s/mst-safereference-with-computed-bug-7qizx

Describe the expected behavior

I'm building a pretty complex application with a lot of models and computed properties (minimal example of usage in codesandbox). Some of the models require safeReference to be used. But it doesn't work.

Currently, as a workaround, I'm using raw value of rootStore.list instead of rootStore.list.asArray workaround for arrays (not sure if I still need it, do I?), but even if there is no need for asArray for arrays I'm not sure it won't break someday in another way while using several nested views.

Describe the observed behavior

When I've tried to use several nested computed (views) with safeReference in one of my models, got an error (see codesandbox for details):

Error: [mobx] Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: [email protected]
bug

Most helpful comment

The issue seems to be related to lazy initialization.
slice() in theory shouldn't do any changes in the model, but actually it is accessing all the items in the list and therefore lazy initializing them, and since it is done inside a getter it throws that.

That being said it should be an exception to that error, therefore I think it's a bug

All 3 comments

I've played with it and got a version where I haven't used safeReference but it still showed me the same error, so maybe it's not really related. Can't reproduce it again though.

The issue seems to be related to lazy initialization.
slice() in theory shouldn't do any changes in the model, but actually it is accessing all the items in the list and therefore lazy initializing them, and since it is done inside a getter it throws that.

That being said it should be an exception to that error, therefore I think it's a bug

My workaround for this is:

export function safeReference(T) {
  return t.reference(T, {
    get(identifier, parent) {
      return resolveIdentifier(T, parent, identifier);
    },
    set(value) {
      return value;
    },
  });
}

It simply returns undefined for unresolved references.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

elado picture elado  路  4Comments

benkuly picture benkuly  路  3Comments

FredyC picture FredyC  路  3Comments

mshibl picture mshibl  路  3Comments

tahv0 picture tahv0  路  3Comments