Flux Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch
Asked Answered
S

4

21

My code https://gist.github.com/ButuzGOL/707d1605f63eef55e4af

So when I get sign-in success callback I want to make redirect,
redirect works through dispatcher too.

And I am getting Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.

Is there any hack to call action in the middle ?

Selfgratification answered 27/10, 2014 at 5:21 Comment(0)
I
27

I don't see where in the gist that you posted you are doing the redirect. I only see the AUTH_SIGNIN and AUTH_SIGNIN_SUCCESS actions, and they look pretty straightforward.

But no, there is no hack to create an action in the middle of a dispatch, and this is by design. Actions are not supposed to be things that cause a change. They are supposed to be like a newspaper that informs the application of a change in the outside world, and then the application responds to that news. The stores cause changes in themselves. Actions just inform them.

If you have this error, then you need to back up and look at how you're handling the original action. Most often, you can set up your application to respond to the original action, accomplish everything you need to do, and avoid trying to create a second action.

Iridis answered 27/10, 2014 at 5:48 Comment(10)
Actually it's very common that for example component A creates an action that changes store B which component C is listening to and in response component C needs to fetch data from server which is an action but the dispatcher is still still dispatching so it cannot. The solution to this feels pretty hacky to me (wrapping the fetch action in a setTimeout or similar)Coucal
I guess it's just best not to cause a dispatch for starting a request (the only reason to do that is to show loading spinners etc anyway, but that is not really application data actually but rather component state)Coucal
Components should not be deciding when to fetch data. This is application logic in the view layer. This logic belongs in the store, which can fire off the XHR and then the error/success callback create actions with the new data.Iridis
Component is not fetching any data but firing an action... and stores firing off actions actually break the one way data flow as it becomes like this pastebin.com/wrWQdFz1Coucal
The one-way data flow in Flux is Action->Dispatcher->Store->View. The cyclic diagram I drew (that you are referencing) was meant to show client-side interactions only. The data flow is still one-way within the Flux application. The data has left the system when the XHR is issued. Data enters the system with the response. As long as you are creating an action in the response and not handling it directly in the store, you have preserved a one-way flow.Iridis
@Iridis this problem has confused me for long time that I want to fire an action after component render, for example, In my view layer, I have a modal dialog which is used to create a item, I fire an action to save the item and the action notify the store that it has done it' job, then the store emitchange to trigger the render that will close the dialog, but I want to reload the data after the component render, what's the best place to handle? currently I use setTimeout to fire a reload action in store after it emitchange, but it looks quite dirty. any suggestion?Kathe
@Kathe this problem has confused me for long time, too! Did you find a solution yet?Skinny
@Kathe Checkout this: github.com/facebook/flux/issues/138, some solutions has provided and fisherwebdev said that debounce the change events is the best solution.Skinny
@Skinny have a look at redux, and redux-saga, I thought, that's the answer of this problemKathe
@Sean, ok, I'll check it now.Skinny
P
6

You can make it work by "scheduling" the next action instead of calling it directly, here is an example code:

// instead of doing this
Dispatcher.dispatch(...);

// go like this
setTimeout(function() {
  Dispatcher.dispatch(...);
}, 1);

This will cause your next dispatch to be called later out of the current dispatch process, and no error will happen.

If your dispatch code is on a callback any kind of other async operation that will work as well (for example in a response for an Ajax request).

I'm using this style to make some forms respond to generic data here and I'm facing no issue, at least the way I'm using it.

Pierpont answered 2/4, 2015 at 22:53 Comment(2)
uuughhh - setTimeout hacks are horrible. Better to use promisesBluet
@DanOsborne I don't think promises solve anything here, since they don't automatically end the current thread of execution the way setTimeout does. If I'm misunderstanding, could you post an example? Thanks!Lemuroid
G
-2

you can user the "defer" option in the dispatcher. In your case it would be like:

Dispatcher.dispatch.defer(...);
Gobelin answered 10/10, 2016 at 22:30 Comment(1)
Dispatcher doesn't have defer method. Uncaught TypeError: _dispatcher.dispatcher.dispatch.defer is not a functionCrenel
I
-2

You can check if the dispatcher is dispatching, such as:

if(!MyDispatcher.isDispatching()) {
    MyDispatcher.dispatch({...});
}
Ionic answered 31/3, 2017 at 14:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.