Dispatching further actions when handling actions
Asked Answered
M

2

11

I have a scenario where I feel like I need to dispatch an action in response to another action, and I don't know the best way to sort it out.

An action is dispatched in response to an HTTP response, something like:

type: 'auth'
data: { username: 'tom' }

Because that response was successful, I want to dispatch an action to send the user to the homepage:

type: 'navigate'
date: { where: 'home' }

This seems like a sensible flow to me: this thing happened, so now I want this thing to happen. Trouble is, the Flux Dispatcher doesn't allow this as we are still in the dispatch cycle. I get why dispatching while dispatching is a bad idea.

Some people have solved this with multiple dispatchers, whilst it seems that the Flux authors are sure that you only need one and that you need to rethink your stores.

I don't see how I could restructure my stores to facilitate this without obfuscating the intent. My UserStore knows about auth actions, and my RouteStore knows about navigate actions. Any suggestions on how the stores could be changed to facilitate this would be appreciated.

I feel like a setImmediate would work, but it seems a bit dirty. I also think a dispatcher that queued actions might help but I can feel in my bones that this could cause nasty problems.

What is the best way out of this?

Manteau answered 14/11, 2014 at 16:49 Comment(0)
Q
4

Usually, the solution to this problem is to to back up and look at the original action, and to waitFor the value that you are trying to send in the second action, if a derived value is required.

So in this case you would respond only to 'auth' in both the UserStore and the RouteStore.

Quintinquintina answered 15/11, 2014 at 17:26 Comment(3)
Thanks for the reply. It seems a little odd to have the route store respond to with actions, but I guess I don't quite have the feel of stores down correctly yet. I think this is where the application logic makes its way into the stores, which feels a little uncomfortable, but then again most of React/Flux feels backwards initially then works out much better than the 'old way' in the end!Manteau
I'll try this out and accept the answer if it works out. I might need to rejig my router a little bit.Manteau
Stores should contain almost all of your application logic, in addition to your application state. They are the locus of all control within a Flux application. One might draw a parallel between Flux stores the ideal of "fat models" in some MVC communities, like Rails. They are "fat" because that's where all the state and logic lives.Quintinquintina
M
8

You should look back how you are trying to create this flow.

You say that you need to create an action in response to another action, right? So, let's name this the "ActionForwarderStore".

We end up with a flow like this:

AuthAction --> Dispatcher --+--> UserStore
                            |
                            +--> ActionForwarderStore --+
                                                        |
           +--------------------------------------------+
           |
           +-> Dispatcher -----> RouteStore

You see that you still have someone that understands that a AuthAction should end up changing a route? This is the ActionForwarderStore. As Flux suggests that every Store listens to every Action, this knowledge of the AuthAction ending up in a route change can go straight into RouteStore. Like this:

AuthAction --> Dispatcher --+--> UserStore
                            |
                            +--> RouteStore

Remember that Flux was "created" in order to avoid the unpredictability of MVC. If you keep all your route changes into RouteStore, you just need to look at this Store code to understand what Actions will cause a route change. If you go in the way of creating an action in response to another action, you will only know that NavigateAction changes routes, and you will need to look at the other Stores to check which ones are triggering this Action in response to others.

This is what Flux names as "unidirectional flow". It's easy to catch problems this way because this is the only flow allowed. If you click a button and it changes the route, you can know for sure that the action that the click dispatched is causing the route change, there are no cascading actions.

Maltese answered 19/12, 2014 at 15:54 Comment(0)
Q
4

Usually, the solution to this problem is to to back up and look at the original action, and to waitFor the value that you are trying to send in the second action, if a derived value is required.

So in this case you would respond only to 'auth' in both the UserStore and the RouteStore.

Quintinquintina answered 15/11, 2014 at 17:26 Comment(3)
Thanks for the reply. It seems a little odd to have the route store respond to with actions, but I guess I don't quite have the feel of stores down correctly yet. I think this is where the application logic makes its way into the stores, which feels a little uncomfortable, but then again most of React/Flux feels backwards initially then works out much better than the 'old way' in the end!Manteau
I'll try this out and accept the answer if it works out. I might need to rejig my router a little bit.Manteau
Stores should contain almost all of your application logic, in addition to your application state. They are the locus of all control within a Flux application. One might draw a parallel between Flux stores the ideal of "fat models" in some MVC communities, like Rails. They are "fat" because that's where all the state and logic lives.Quintinquintina

© 2022 - 2024 — McMap. All rights reserved.