Skip to content

Allow injection of a dispatch wrapper#100

Closed
BinaryMuse wants to merge 8 commits intomasterfrom
features/bkt-dispatcher-batching-function
Closed

Allow injection of a dispatch wrapper#100
BinaryMuse wants to merge 8 commits intomasterfrom
features/bkt-dispatcher-batching-function

Conversation

@BinaryMuse
Copy link
Copy Markdown
Owner

React automatically batches updates when inside a synthetic event handler, but asynchronous updates do not get the same treatment. Consider the following scenario:

  1. A button in ComponentA calls an action creator
  2. The action creator calls an async API
  3. As a result of the async call, the action creator dispatches an action
  4. That action sets new state in a store
  5. The new store data causes a new child to be mounted inside ComponentA (let's call it ComponentB)
  6. ComponentB fires an action immediately, via componentDid/WillMount

Unlike re-renders from synchronous action dispatches (which generally happen in the context of a synthetic event), asynchronous dispatches aren't called within the context of React's batching strategy. This means the dispatch loop is still in progress when ComponentB mounts, causing a cascading dispatch exception.

Flux#setDispatchWrapper allows you to pass a function to wrap dispatches in; in most (all?) cases, you'll want to pass React.addons.batchedUpdates (or some custom function that calls it) in order to force all dispatches to happen in the context of React's batched updates.

Fixes #92

@BinaryMuse BinaryMuse force-pushed the features/bkt-dispatcher-batching-function branch from fa3ca9f to f6101c2 Compare February 3, 2015 07:40
@BinaryMuse BinaryMuse changed the title Allow injection of a batching function to wrap dispatches Allow injection of a dispatch wrapper Feb 3, 2015
@nelix
Copy link
Copy Markdown

nelix commented Feb 4, 2015

This is pretty useful, I was hoping to be able to use it to replay dispatches and to send them via postMessage (for example, when having stores in a sharedWorker).

@BinaryMuse
Copy link
Copy Markdown
Owner Author

@nelix Not sure quite what you mean about dispatch replaying; can you clarify?

As for alternative dispatch implementations, what about an API that looked more like this?

flux.setDispatchWrapper(function(action, dispatch));

where action is the action being dispatched and dispatch is the original dispatch function (on the dispatcher). So, the vanilla implementation would be

flux.setDispatchWrapper(function(action, dispatch) {
  dispatch(action);
});

and the batchedUpdates case would be

flux.setDispatchWrapper(function(action, dispatch) {
  React.addons.batchedUpdates(function() {
    dispatch(action);
  });
});

and custom implementations (e.g. with web workers) could forego the original implementation completely:

flux.setDispatchWrapper(function(action) {
  worker.postMessage({action: action});
});

(FWIW, these kinds of scenarios will be much better supported by the v2 API, which I swear I'm working on :)

@nelix
Copy link
Copy Markdown

nelix commented Feb 5, 2015

That would do nicely.
By replay I mean so I could implement something like flux-hot-loader, when store.js gets updated and reloader, all the dispatches get replayed so it keeps its state.

Brandon Tilley added 5 commits April 5, 2015 15:22
React automatically batches updates when inside a synthetic event
handler, but asynchronous updates do not get the same treatment.
Consider the following scenario:

1. A button in ComponentA calls an action creator
2. The action creator calls an async API
3. As a result of the async call, the action creator dispatches an action
4. That action sets new state in a store
5. The new store data causes a new child to be mounted inside ComponentA
   (let's call it ComponentB)
6. ComponentB fires an action immediately, via componentDid/WillMount

Unlike re-renders from synchronous action dispatches (which generally
happen in the context of a synthetic event), asynchronous dispatches
aren't called within the context of React's batching strategy. This means
the dispatch loop is still in progress when ComponentB mounts, causing
a cascading dispatch exception.

`Flux#setBatchingFunction` allows you to pass a batching function to
wrap dispatches in; in most (all?) cases, you'll want to pass
`React.addons.batchedUpdates` in order to force all dispatches to happen
in the context of React's batched updates.

Fixes #92
@BinaryMuse BinaryMuse force-pushed the features/bkt-dispatcher-batching-function branch from 56a65e4 to 7ac2074 Compare April 5, 2015 23:41
@BinaryMuse
Copy link
Copy Markdown
Owner Author

Updated the API to setDispatchInterceptor and allows custom functions as per my previous comment.

@BinaryMuse
Copy link
Copy Markdown
Owner Author

Landed in master as d35b604...b35d28b

@BinaryMuse BinaryMuse closed this May 1, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Trigger this.emit( 'change' ); after dispatch ends

3 participants