Modifying tree in reaction give the error:
Cannot modify 'Store@<root>', the object is protected and can only be modified by using an action.
So my conclusion is that reactions should be treated specially, like in a solution bellow.
Is that right, there are other solutions?
Here is my code and the solution in comment:
export const Store = types
.model({
app: types.maybe(AppModel),
nav: types.optional(NavModel, {}),
form: types.maybe(FormModel),
})
.named('Store')
.actions(me => ({
createForm() {
me.form = FormModel.create({})
},
}))
.actions(me => ({
afterCreate() {
me.app = AppModel.create({})
console.log('creating app')
reaction(
() => me!.app!.auth,
auth => {
if (auth) {
console.log('creating form')
// me.createForm()
me.form = FormModel.create({})
} else {
console.log('destroying app')
me.app && destroy(me.app)
me.form && destroy(me.form)
}
},
)
},
}))
.create({})
tried to quickly reproduce it without any luck. could you provide a sandbox?
i have a certain idea about it - but would like to verify that :)
so before the explanation:
the reaction should use actions again as you did already within your comments.
even if used within the scope.
the explanation for this is as follows:
when you invoke .create() on a model you get a node - in your case a node with sub nodes because there are more sub models. each action you declare gets wrapped and bound to a node on .create() - so MST can mark the node as "isRunningAction" when an action gets invoked. only if an action is running on the node - in your case the "App" node - manipulations are allowed for such. your reaction though is on the "Store" node, not the "App" node.
what quickly confused me was that the reaction worked if you'd invoke an action on the "Store" node instead of on the "App" node. that worked because the flag "isRunning" is set for the right node and it is not set back to false before the reaction did run too.
Thanks Rob!
Most helpful comment
so before the explanation:
the reaction should use actions again as you did already within your comments.
even if used within the scope.
the explanation for this is as follows:
when you invoke
.create()on a model you get a node - in your case a node with sub nodes because there are more sub models. each action you declare gets wrapped and bound to a node on.create()- so MST can mark the node as "isRunningAction" when an action gets invoked. only if an action is running on the node - in your case the "App" node - manipulations are allowed for such. your reaction though is on the "Store" node, not the "App" node.what quickly confused me was that the reaction worked if you'd invoke an action on the "Store" node instead of on the "App" node. that worked because the flag "isRunning" is set for the right node and it is not set back to false before the reaction did run too.