i'm trying to use React with Flux architecture and stumbled on one restriction which i can't handle. Problem is as following:
Best solution i came up with so far is wrapping inner dispatch in setTimeout(f, 0)
, but it looks scary.
Actually the problem is quite general - how should i organize dispatch chain without dispatch nesting (without violating current Flux restrictions) if each new dispatch is based on previous dispatch handling result.
Does anybody have any good approaches to solve such problems?
var selectItem(item) {
AppDispatcher.dispatch({
actionType: AppConstants.ITEM_SELECT,
item: item
});
}
// Item must be requested and selected.
// If it's in store - select it.
// Otherwise fetch and then select it.
SomeStore.dispatchToken = AppDispatcher.register((action) => {
switch(action.actionType) {
case AppConstants.ITEM_REQUESTED:
var item = SomeStore.getItem(action.itemId);
if (item) {
// Won't work because can't dispatch in the middle of dispatch
selectItem(item);
} else {
// Will work
$.getJSON(`some/${action.itemId}`, (item) => selectItem(item));
}
}
};
Are you writing your own dispatcher? setTimeout(f, 0)
is a fine trick. I do the same thing in my minimal flux here. Nothing scary there. Javascript's concurrency model is pretty simple.
More robust flux dispatcher implementations should handle that for you.
If ITEM_SELECT
is an event that another Store
is going to handle:
You are looking for dispatcher.waitFor(array<string> ids): void
, which lets you use the SomeStore.dispatchToken
that register()
returns to enforce the order in which Stores handle an event.
The store, say we call it OtherStore
, that would handle the ITEM_SELECT
event, should instead handle ITEM_REQUEST
event, but call dispatcher.waitFor( [ SomeStore.dispatchToken ] )
first, and then get whatever result is interesting from SomeStore
via a public method, like SomeStore.getItem()
.
But from your example, it seems like SomeStore doesn't do anything to its internal state with ITEM_REQUEST
, so you just need to move the following lines into OtherStore
with a few minor changes:
// OtherStore.js
case AppConstants.ITEM_REQUESTED:
dispatcher.waitFor( [ SomeStore.dispatchToken ] );// and don't even do this if SomeStore isn't doing anything with ITEM_REQUEST
var item = SomeStore.getItem(action.itemId);
if (item) {
// Don't dispatch an event, let other stores handle this event, if necessary
OtherStore.doSomethingWith(item);
} else {
// Will work
$.getJSON(`some/${action.itemId}`, (item) => OtherStore.doSomethingWith(item));
}
And again, if another store needs to handle the result of OtherStore.doSomethingWith(item)
, they can also handle ITEM_REQUESTED
, but call dispatcher.waitFor( [ OtherStore.dispatchToken ] )
before proceeding.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With