mobx: Computed triggering the creation of an observable map invariant failed
I’m having issues with computeds and observable map creation.
I have a very simple test case here: https://jsfiddle.net/7e6Ltscr/
I get the following error:
VM103:59 Uncaught Error: [mobx] Invariant failed: Computed values or transformers should not invoke actions or trigger other side effects
at mt (mobx.umd.min.js:2)
at B (mobx.umd.min.js:2)
at P (mobx.umd.min.js:2)
at V (mobx.umd.min.js:2)
at e.merge (mobx.umd.min.js:3)
at mobx.umd.min.js:3
at H (mobx.umd.min.js:2)
at new e (mobx.umd.min.js:3)
at Function.e.map (mobx.umd.min.js:2)
at form (VM103:59)
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Comments: 22 (21 by maintainers)
Commits related to this issue
- Computed triggering the creation of an observable map invariant failed #798 Adding a unit test. — committed to mobxjs/mobx by mattruby 7 years ago
- Computed triggering the creation of an observable map invariant failed #798 Altered the initial map.merge to really be untracked. — committed to mobxjs/mobx by mattruby 7 years ago
- Can now invoke actions from computed, see #798 — committed to mobxjs/mobx by mweststrate 7 years ago
- Computed triggering the creation of an observable map invariant failed #798 Added a map.set into the test case. The tests are now broken. — committed to mobxjs/mobx by mattruby 7 years ago
- Improved strict mode as discussed in #798 — committed to mobxjs/mobx by mweststrate 7 years ago
- Merge pull request #812 from mobxjs/fix/798-invoke-action-from-computed Relax strict mode, solves #798, #563 — committed to mobxjs/mobx by mweststrate 7 years ago
Released as 3.1.0 😃
Ok, I think the current solution is overly complicated, both from technical perspective and to explain. I think it could simply work by changing the semantics to:
It basically means strict mode is relaxed to only protect observed state. This avoids jumping through hoops when creating and initializing new state as described in this issue and #563.
Just to make things clear - please correct me if I am wrong: Returning new observables from derivations (computed) is already supported… I do this all the time (with 2.x):
There are two inconveniences though - the constructor can’t modify observables (even outside of strict mode) and can’t invoke any actions (which is kind of the same thing).
As a consequence all initialization logic must be done before the observables are introduced and actions can’t be invoked as initializers from constructor or from computed itself.
So the guard is not about returning new observables, but it allows mutating unobserved state from derivation (the action si required in strict mode, but has no practical use in this case). Shouldn’t the computed allow to mutate only an unobserved state created inside the computed, similary to constructors?
However I am not sure if this should be a fix for this particular issue - imho the ObservableMap simply shoudn’t call any actions (modify state) during it’s initialization in the first place.