Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Flux - dispatching within a dispatch - how to avoid?

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.

  1. First, the login button is rendered in Wrapper component.
  2. Clicking the button dispatches the LOGIN action.
  3. After a delay, the LOGIN_RESPONSE action is dispatched (via the async mechanism in alt.js).
  4. This action triggers MyStore to update the user name.
  5. Wrapper component observes the store change and updates its state.
  6. This causes Wrapper to render Content component instead of the login button.
  7. Content component, on mount, attempts to dispatch the FETCH_DATA action, which fails because the dispatcher is still dispatching LOGIN_RESPONSE. (If I wrap the FETCH_DATA dispatch in a setTimeout it 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?

like image 814
Ian Su Avatar asked Jan 16 '16 15:01

Ian Su


1 Answers

This is a common problem with dispatching in componentDidMount in many libraries. The solution is to wrap dispatches in React's batched updates; luckily, Alt allows you to do this with the batchingFunction option:

var alt = new Alt({
  // React.addons.batchedUpdates is deprecated:
  // batchingFunction: React.addons.batchedUpdates

  // use this instead in newer versions of React
  // see https://discuss.reactjs.org/t/any-plan-for-reactdom-unstable-batchedupdates/1978
  batchingFunction: ReactDOM.unstable_batchedUpdates
});

See https://jsfiddle.net/BinaryMuse/qftyfjgy/ for a working example and this Fluxxor issue for a description of the same problem in a different framework.

like image 61
Michelle Tilley Avatar answered Nov 05 '22 02:11

Michelle Tilley