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

16,944

Solution 1

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.

Solution 2

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.

Share:
16,944

Related videos on Youtube

ButuzGOL
Author by

ButuzGOL

Working with JavaScript in deep

Updated on April 01, 2020

Comments

  • ButuzGOL
    ButuzGOL about 4 years

    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 ?

  • Esailija
    Esailija over 9 years
    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)
  • Esailija
    Esailija over 9 years
    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)
  • fisherwebdev
    fisherwebdev over 9 years
    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.
  • Esailija
    Esailija over 9 years
    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/wrWQdFz1
  • fisherwebdev
    fisherwebdev over 9 years
    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.
  • Sean
    Sean almost 9 years
    @fisherwebdev 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?
  • Dan Osborne
    Dan Osborne over 8 years
    uuughhh - setTimeout hacks are horrible. Better to use promises
  • Lane Rettig
    Lane Rettig over 8 years
    @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!
  • backslash112
    backslash112 over 8 years
    @Sean this problem has confused me for long time, too! Did you find a solution yet?
  • backslash112
    backslash112 over 8 years
    @Sean Checkout this: github.com/facebook/flux/issues/138, some solutions has provided and fisherwebdev said that debounce the change events is the best solution.
  • Sean
    Sean over 8 years
    @backslash112 have a look at redux, and redux-saga, I thought, that's the answer of this problem
  • backslash112
    backslash112 over 8 years
    @Sean, ok, I'll check it now.
  • rosencreuz
    rosencreuz over 6 years
    Dispatcher doesn't have defer method. Uncaught TypeError: _dispatcher.dispatcher.dispatch.defer is not a function