I'm trying to figure out how to do sequential actions on startup. In my case this sort of looks like this in pseudo-code:
App.start()
.then(getSetup)
.then(fetchLocales)
.then(fetchOffers)
We need getSetup action to finish before calling fetchLocales, as the setup store contains info we need for fetching the locales data... Any guidance here?
After store creation you can do store.dispatch(somePropmiseChain) you need redux-promise middleware as well I suppose to use promises as action creators.
@StevenLangbroek You could use the thunk middleware to create a bootstrap action creator, which contains your full promise chain and dispatches actions on the go.
Sorry I should've been a bit more clear maybe. The chain looks more like this:
getSetup().
then(setup =>
// How do I ensure this has been reduced into the store...
dispatch({
type: FETCH_SETUP,
payload: setup
})
)
// ...before running this action? fetchTranslations needs
// a subnode of the `setup` store...
.then(fetchTranslations)
.then(translations =>
dispatch({
type: FETCH_TRANSLATIONS,
payload: translations
})
)
.then(fetchOffers)
.then(offers => dispatch({
type: FETCH_OFFERS,
payload: offers
}));
@StevenLangbroek how about something like this:
import { getSetup, fetchTranslations, fetchOffers} from './utils/api';
const actioncreator = {
bootstrap() {
return (dispatch, getState) => {
getSetup()
.then(setup => dispatch({
type: FETCH_SETUP,
payload: setup
}))
.then(() => {
// since `dispatch` is synchronous a call to `getState` will yield you the current state
const subNode = getState().something.subNode;
return fetchTranslations(subNode);
})
.then(translations => dispatch({
type: FETCH_TRANSLATIONS,
payload: translations
}))
.then(fetchOffers)
.then(offers => dispatch({
type: FETCH_OFFERS,
payload: offers
}));
}
}
}
It's not tested but you get the idea.
Right, ok, that makes sense. I've been toying with this, but the next problem is that the fetchOffers action is also a stand-alone action, so it's curried, and should receive dispatch, getState in the 2nd function...
@StevenLangbroek If it doesn't fit the dispatch format, you can always just write a wrapper to do it for you. It's not optimal, but that's how most people do it. Or convince management/upstream to change it (less likely to be successful).
You can use redux-combine-actions for sequential actions.
It will look something like this:
export function fetchData() {
return {
types: [
'COMBINED_ACTION_START',
'COMBINED ACTION_SUCCESS',
'COMBINED ACTION_ERROR'
],
// Set true for sequential actions
sequence: true,
// Pass actions in array
payload: [getSetup, fetchTranslations, fetchOffers]
};
}
This will dispatch actions in the following sequence:
_COMBINED_ACTION_START_ -> _FETCH_SETUP_ -> _FETCH_TRANSLATIONS_ -> _FETCH_OFFERS_ -> _COMBINED_ACTION_SUCCESS_
@itsmepetrov your middleware looks interesting. Could you update the readme explaining how to apply it , how does the types array work, etc.?
Thanks!
@nickdima I've updated documentation for the middleware and I hope docs will answer your questions. But I'm always glad to help.
@itsmepetrov much better! Thanks!
Closing, as seems resolved by either redux-combine-actions or manual action creator composition with redux-thunk.
Most helpful comment
@StevenLangbroek how about something like this:
It's not tested but you get the idea.