mobx-state-tree icon indicating copy to clipboard operation
mobx-state-tree copied to clipboard

getParent returns undefined

Open Ghirigoro opened this issue 5 years ago • 5 comments

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

Sandbox link or minimal reproduction code Sandbox: https://codesandbox.io/s/heuristic-sound-kl7kd Example:

import { types, getParent, isRoot, hasParent } from "mobx-state-tree";

const ChildModel = types.model("Child", {})
.actions(self => ({
  afterAttach() {
    console.log("Is Root:", isRoot(self)); // false
    console.log("Has Parent:", hasParent(self)); // true
    console.log("Parent:", getParent(self)); // undefined. Why?
  }
}));

export const ParentModel = types.model("Parent", {
  child: types.optional(ChildModel, () => ChildModel.create())
});

const parent = ParentModel.create();

Describe the expected behavior Should be able to retrieve parent instance from child in afterAttach hook. I.e. the logs should show:

Is Root: false
Has Parent: true
Parent: { child: { } }

Describe the observed behavior Child is not the root and has parent but getParent returns undefined. I.e. the logs show:

Is Root: false
Has Parent: true
Parent: undefined

Ghirigoro avatar Mar 21 '20 14:03 Ghirigoro

I think youre not supposed to use the create method inside the model property definitions. Instead, just pass it a valid object for the model you want to create. This works for your example:

export const ParentModel = types.model("Parent", {
  child: types.optional(ChildModel, {})
});

IngoValente avatar Apr 10 '20 10:04 IngoValente

@IngoValente Thanks! I don't think the problem is that you're not allowed to invoke the create method of a model inside the definition (especially for a different model). Instead I think your example shows that you have to provide a snapshot of the type instead of an instance of the type, and that is more likely the answer.

Ghirigoro avatar Apr 10 '20 14:04 Ghirigoro

I'm running into exactly this problem too.

maccman avatar Dec 19 '20 00:12 maccman

I'm facing a similar problem.

Upward-Spiral avatar Dec 14 '21 15:12 Upward-Spiral

I met the same problem. and solved it

import { types, getParent, isRoot, hasParent } from "mobx-state-tree";

const ChildModel = types.model("Child", {})
.actions(self => ({
  afterAttach() {
    console.log("Is Root:", isRoot(self)); // false
    console.log("Has Parent:", hasParent(self)); // true
    console.log("Parent:", getParent(self)); // ParentModelInstance ,as expected
  }
}));

export const ParentModel = types.model("Parent", {
  child: types.maybeNull(ChildModel) // don't create child here
})
.actions(self => ({
  afterCreate() {
    self.child = ChildModel.create({}) // create child after parent creation
  }
}))

const parent = ParentModel.create();

I guess when childModel's afterAttach method is called during definning parent model, At this time, parent model has not been created, so you can't get it.

Anoninz avatar Apr 15 '22 06:04 Anoninz

Hey folks - sorry it's been a while with inactivity on this MST issue.

I think that https://github.com/mobxjs/mobx-state-tree/pull/1952 might also be the overall fix here. There are a bunch of issues about these lifecycle hooks.

I'm going to tag this issue to indicate it has a PR to fix already, and hopefully add to the list of issues we can resolve with that PR.

Thanks for all the discussion!

coolsoftwaretyler avatar Jun 30 '23 03:06 coolsoftwaretyler

Closing this out because that PR was merged. Please let me know if you still have the same issue on latest MST!

coolsoftwaretyler avatar Nov 29 '23 07:11 coolsoftwaretyler