-
Notifications
You must be signed in to change notification settings - Fork 642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Nested Models, and actions dependencies #486
Comments
Uhm, have you considered using addMiddleware instead of onAction? It will give you more control over async actions :) |
Yes I can try that 😃 |
I think that both are valid ones, the latest one is more agnostic about how the data is shaped, ideally you can implement a service-command pattern based on that :) |
I personally like the look of it as a tree @fabienjuif, better than a graph like you described in your last one. I would definitely be interested to see if you managed to get it working with async. Perhaps it could be a blog post? |
I did have one thought tho. Wouldnt it be more "reactive" if your root Store listened to a "isLoggedIn" property on your AuthStore then redirected the Routes Store to "gotoList" when "isLoggedIn" value becomes "true" ? Im not sure if thats a better approach than listening to the action itself however... |
Hi @mikecann I will post here my progress. About property checking and reacting to them, I though about it, but I don't like it neither:
|
Note that you can setup reactions in the afterCreate of your RouterStore, to listen indeed to something from which you can deduct that the user is now logged in. It might feels as closer coupling indeed as your approach, but the advantage is that it is also typecheckable :) Which is a downside of your proposal. That being said, the thing you propose should work just fine as well |
In the Flux/Redux world, this is usually solved using two actions for async actions. Actually, three actions: Router can subscribe (listen) only to If you don't want to pollute your stores with app logic, you can leave that to external actors. Like you mentioned, something similar to redux-saga, but you'd need an external dispatcher. This is just an idea about a possible implementation without using an external dispatcher: const Auth = types.model('Auth')
.props({
logging: false,
error: types.maybe(types.string),
userId: types.maybe(types.string),
})
.actions(self => {
const loginRequested: () => { self.logging = true; login(); };
const loginSucceed: userId => { self.logging = false; self.userId = userId };
const loginFailed: error => { self.logging = false; self.error = error };
const login = flow(function* () {
try {
const userId = yield fetch(...); // your login logic
self.loginSucceed(userId);
} catch (error) {
self.loginFailed(error);
}
});
return {
loginRequested,
loginSucceed,
loginFailed,
}
})); Then in the middleware, you capture the |
Just note that |
Thanks @mattiamanzati. I have edited
|
@luisherranz in your example, wouldnt that then expose "loginSucceed" and "loginFailed" to the outside world thus breaking encapsulation? I know this is sort of what is required here but is this a good idea for clean code? |
@luisherranz yes this is one of the possibles implementations of the But I don't see how it preserve us from doing a middleware that listen to actions 🤔 |
@mikecann Yes, in a Redux/Flux system all actions are public!
@fabienjuif The whole point was that having a separate That said, I think the ideal scenario (if going the Flux route) would be having an external dispatcher and manage the logic in async/generator functions, like redux-saga. |
I wrote a middleware that I can use like this : const dispatch = (action, tree) => {
const { fullpath, ended } = action
if (fullpath === '/auth/login' && ended) {
tree.ui.router.goToList()
}
}
addMiddleware(store, trampssReact(dispatch)) It works well right now 😄 I still have a little issue (maybe it's not):
That's why I added I will create a new repo with this first middleware implementation. I come back soon. |
Voila: https://github.com/Trampss/trampss-mst-onaction In fact, after all the digging this is just a simpler API of a middleware 😛 The function given to
The action has :
|
Looks great @fabienjuif! |
@fabienjuif thats cool! Would love to see some tests that it works under all situations (errors, async, non-async) etc |
Right now @mikecann it works with
I use it right now for theses both cases in my project. Errors -> this is something to dig, I haven't test this yet |
Is there a way to know if the action is async in the first place? Something like |
Yes it would be great, but I don't see how I can have this information the first time the action is triggered. In the @mattiamanzati can you confirm that ? edit: right now I try to write some helpers to match actions :) |
@fabienjuif you can detect it by checking in your action middleware whether a The action tracking middleware makes that process much simpler btw. Give me some time to publish that (you can see how it is used in the Undo/Redo middleware |
I changed the API a bit in this PR : unirakun/k-mst-onaction#6 (comment) It uses helpers, I'm not really sure about this. On this PR I try an array implementation : unirakun/k-mst-onaction#7 What do you think is better as a user perspective ? |
@fabienjuif I do like the array implementation! Do you have any thoughts/preferences for dealing with map keys or array indexes being part of the
I think it would be handy to be able to capture the |
@wbercx I see that @fabienjuif added support for regexps, maybe he can add support for https://github.com/pillarjs/path-to-regexp
|
I could :) |
I have the feeling the main issue from this topic is resolved. I close this topic so the *mobx-state-tree issue tab is less flooded :) If you don't agree, feel free to argue ;) |
Hi there :)
I use mobx-state-tree for a project, and I would like to use it as my main store.
I have nested models and I would like to avoid having a graph definition, and instead I would like to have a tree (composition).
So I tried something that I explain below, but I don't like it. I ask some question at the end, feel free to ask more if you don't understand 👍
Store
Actions with
getRoot
What I do right now, while my user needs to login is :
Auth
model has to know theRouter
modelActions with
onAction
fromStore
modelSo I tried to use
onAction
into theStore
model, listening tologin
then callinggoToList
:onAction
redux-saga
implementationWhat's the problem ?
The problem is that this
onAction
way of writing my actions dependencies works well with synchronous actions, but not with asynchronous one (?? this is to confirm)login
action is asynchronousgoToList
is synchronouslogin
action is triggered and caught byonAction
at the beginning, not a the end of theprocess
goToList
) before my user is logged, that is not fine here.What's the solutions ?
Question
Thank you !
The text was updated successfully, but these errors were encountered: