I have:
[x] I think something is not working as it should.
[x] Describe expected behavior
I want to call action from another action in Typescript.
The only way to do it is via (self as any).anotherAction() as "self" is only typed for props in action.
Is there any other way?
[ ] Describe observed behavior
_Not following the above template might result in your issue being closed without further notice_
For now one of the alternatives is separating them
types.model({x: 5})
.actions(self => ({
a1() {}
})
.actions(self => ({
a2() {
self.a1()
}
}))
another alternative is (don't use this trick for views since if you do views won't be computed)
types.model({x: 5})
.actions(self => {
const actions = {
a1() {},
a2() { actions.a1() }
}
return actions
})
for new alternatives being proposed please check https://github.com/mobxjs/mobx-state-tree/issues/982
See also: https://github.com/mobxjs/mobx-state-tree#typing-self-in-actions-and-views
Thank you all for your answers. I have A LOT of different approaches. I'm sorry I missed that bit in the documentation. I read it quite a few times ...
@mweststrate I tried to use the following approach from https://github.com/mobxjs/mobx-state-tree#typing-self-in-actions-and-views but TypeScript 3 doesn't like it. I think Example becomes any if referenced inside its initialization.
const Example = types
.model("Example", { prop: types.string })
.views((self: typeof Example.Type) => ({
// use typeof instead of predefined type to avoid circular references
get upperProp(): string {
return self.prop.toUpperCase()
},
get twiceUpperProp(): string {
return self.upperProp + self.upperProp
}
}));
The error is:
[ts] 'Example' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.
@malekpour
try this instead
const Example = types
.model("Example", { prop: types.string })
.views((self) => ({
get upperProp(): string {
return self.prop.toUpperCase()
}
}))
.views((self) => ({
get twiceUpperProp(): string {
return self.upperProp + self.upperProp
}
}));
or alternatively this
const Example = types.model("Example", { prop: types.string }).views(self => ({
get upperProp(): string {
return self.prop.toUpperCase()
},
get twiceUpperProp(): string {
return this.upperProp + this.upperProp
}
}))
@malekpour just fixed the readme with the "this" approach rather than the incorrect typeof one, thanks for pointing it out!
unit test used to make sure it was right
const Example = types.model("Example", { prop: types.string }).views(self => ({
get upperProp(): string {
return self.prop.toUpperCase()
},
get twiceUpperProp(): string {
return this.upperProp + this.upperProp
}
}))
const EI = Example.create({ prop: "hi" })
expect(EI.upperProp).toBe("HI")
expect(EI.twiceUpperProp).toBe("HIHI")
expect(isObservableProp(EI, "upperProp")).toBe(true)
expect(isObservableProp(EI, "twiceUpperProp")).toBe(true)
Strange, in action, this for me is "window".
And this type is any for me.
Type inference depends on the compiler settings, so they might differ
Op di 28 aug. 2018 00:31 schreef Ali Malekpour notifications@github.com:
And this type is any for me.
—
You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub
https://github.com/mobxjs/mobx-state-tree/issues/989#issuecomment-416390236,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABvGhAajIeyWImy3uvjFFA1CavsoCvfiks5uVHM_gaJpZM4WLRCG
.
maybe you are using Arrow functions? The 'this' trick doesn't work with those
or alternatively this
const Example = types.model("Example", { prop: types.string }).views(self => ({ get upperProp(): string { return self.prop.toUpperCase() }, get twiceUpperProp(): string { return this.upperProp + this.upperProp } }))
@xaviergonz
When using flow to write async action, this is implicit, does this means the only solution is writing multiple .action() ?
Can I call action3 in action2?
mstModel
.actions((self) => ({
action1: flow(function*() {
console.log('this is action1');
}),
}))
.actions((self) => ({
action2: flow(function*() {
self.action1(); // right
self.action3(); // wrong
console.log('this is action2');
}),
}))
.actions((self) => ({
action3: flow(function*() {
console.log('this is action3');
}),
}))
Can I call
action3inaction2?mstModel .actions((self) => ({ action1: flow(function*() { console.log('this is action1'); }), })) .actions((self) => ({ action2: flow(function*() { self.action1(); // right self.action3(); // wrong console.log('this is action2'); }), })) .actions((self) => ({ action3: flow(function*() { console.log('this is action3'); }), }))
@xaviergonz
Maybe this is the best solution ?
.actions((self) => {
const actions = {
action1: flow(function*() {
console.log('this is action1');
}),
action2: flow(function*() {
actions.action1(); // right
actions.action3(); // right
console.log('this is action2');
}),
action3: flow(function*() {
console.log('this is action3');
}),
};
return actions;
})
that's a way to solve it yes, however be warned that inter calls between actions won't be actions themselves IIRC
What does that mean? Please tell me more details. Thank You.
Using getRoot and find current model like reflection
.actions(self => ({
a: () => {
const root = getRoot(self)
root.currentModel.b()
},
b: () => {
console.log('called b function')
}
Most helpful comment
unit test used to make sure it was right