I seem to have encountered a situation where I cannot avoid the dispatch-within-a-dispatch problem in Flux.
I've read a few similar questions regarding this problem but none of them seem to have a good solution besides setTimeout hacks, which I would like to avoid.
I'm actually using alt.js instead of Flux but I think the concepts are the same.
Scenario
Imagine a component that initially renders a login form. When a user logs in, this triggers an XHR that eventually responds with authentication information (eg. the user name), and then fetches some secure data based on the authentication information and renders it instead of the login form.
The problem I have is when I attempt to fire an action to fetch data based on the XHR response, it is still in the dispatch of the LOGIN_RESPONSE action, and triggers the dreaded
Error: Invariant Violation: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch.
Example
I have created this jsfiddle to demonstrate the problem.
I have a Wrapper component which either renders a login button or a Contents child component, based on whether the user is set in MyStore.
- First, the login button is rendered in
Wrappercomponent. - Clicking the button dispatches the
LOGINaction. - After a delay, the
LOGIN_RESPONSEaction is dispatched (via the async mechanism in alt.js). - This action triggers
MyStoreto update the user name. Wrappercomponent observes the store change and updates its state.- This causes
Wrapperto renderContentcomponent instead of the login button. Contentcomponent, on mount, attempts to dispatch theFETCH_DATAaction, which fails because the dispatcher is still dispatchingLOGIN_RESPONSE. (If I wrap theFETCH_DATAdispatch in asetTimeoutit works, but it feels like a hack).
Variations of this seems to be a common scenario. In fact almost all the related questions have a similar scenario, but with no good or concrete answers.
- React - Authentication process : Cannot dispatch in the middle of a dispatch
- Dispatching cascading/dependent async requests in Flux/React
- Flux Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch
Is there something intrinsically wrong with this data flow? What is the proper Flux way of doing something like this?