xaviergonz / mobx-keystone

A MobX powered state management solution based on data trees with first class support for Typescript, support for snapshots, patches and much more

Home Page:https://mobx-keystone.js.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Array of models in computedTree

ZFail opened this issue · comments

commented

Does computedTree support an array of models?
I get an error "an object cannot be assigned a new parent when it already has one" when the tree is updated for the second time.
https://codesandbox.io/s/mobx-keystone-computedtree-cscdc

Already checking. I've been able to reproduce the error with this extension of the tests:

--- a/packages/lib/test/computedTree/computedTree.test.ts
+++ b/packages/lib/test/computedTree/computedTree.test.ts
@@ -73,6 +73,14 @@ class R extends Model({
     return ["abc"]
   }
 
+  @computedTree
+  get arrayOfModels() {
+    return [
+      new M({ id: `${this.id}.model1`, value: this.value }),
+      new M({ id: `${this.id}.model2`, value: this.value }),
+    ]
+  }
+
   @computedTree
   get plainObject() {
     return { key: "value" }
@@ -481,3 +489,9 @@ test("computed tree is readonly", () => {
     "tried to invoke action 'setValue' over a readonly node"
   )
 })
+
+test("computed tree works with an array of models", () => {
+  const r = new R({})
+  r.setValue(10)
+  expect(r.arrayOfModels.map((m) => m.value)).toEqual([10, 10])
+})

But I'm not sure yet why the error is happening.

@xaviergonz Do you think

tweak(oldValue, undefined)
tryUntweak(oldValue)

is correct or should entry.tweakedValue be untweaked as well somehow? I've been trying to debug it already but without success so far.

The error is occurring when this line is executed:

This fixes the new test:

--- a/packages/lib/src/computedTree/computedTree.ts
+++ b/packages/lib/src/computedTree/computedTree.ts
@@ -75,8 +75,9 @@ export function computedTree(
       return entry.tweakedValue
     }
 
-    tweak(oldValue, undefined)
-    tryUntweak(oldValue)
+    const oldTweakedValue = entry.tweakedValue
+    tweak(oldTweakedValue, undefined)
+    tryUntweak(oldTweakedValue)
 
     const tweakedValue = tweakComputedTreeNode(newValue, this, propertyKey)
     entry.value = newValue

But the getChildrenObjects and walkTree tests are failing then. 🤔

My bad, those tests need to be adapted.

I'll submit a PR with a fix later today.

Fixed in v1.1.1. Thanks!