I am trying to chain dispatches with redux thunk
function simple_action(){ return {type: "SIMPLE_ACTION"} } export function async_action(){ return function(dispatch, getState){ return dispatch(simple_action).then(()=>{...}); } }
How do I get the dispatch to return a promise from the store?
MORE SPECIFICALLY:
I am probably just not understanding something here, but in all the examples with redux-thunk
, they call a separate async event (like fetch
), which obviously returns a Promise
.
What I'm specifically looking for is when I dispatch an action to the store: How do I make certain the store has processed that action completely before anything else happens in the function action_creator()
above.
Ideally, I would like the store to return some sort of promise, but I don't understand how or where that happens?
store. dispatch returns something that is not a promise.
To make redux-promise work, configure it with the store so that once the app hits the server endpoint, the promise will start triggering the actions. Before applying the middleware, the Redux store needs to be created, as shown below.
To dispatch async actions into our store, we have to apply the thunk middleware by writing: const store = createStore(joke, applyMiddleware(thunk)); to apply the middleware. Then in App , we call dispatch with the function returned from the fetchJoke passed inside.
An action creator is merely a function that returns an action object.
Here you have an example on how to dispatch and chain async action. https://github.com/gaearon/redux-thunk
The thunk middleware knows how to turn thunk async actions into actions, so you just have to have your simple_action() to be a thunk and the thunk middleware will do the job for you, if the middleware see a normal action, he will dispatch this action as normal action but if it's an async function it will turn your async action into normal action.
So your simple_action need to be a thunk ( A thunk is a function that returns a function.) Like this for example:
function makeASandwichWithSecretSauce(forPerson) { return function (dispatch) { return fetchSecretSauce().then( sauce => dispatch(makeASandwich(forPerson, sauce)), error => dispatch(apologize('The Sandwich Shop', forPerson, error)) ); }; }
When using the makeASandwichWithSecretSauce function you can use the dispatch function
store.dispatch( makeASandwichWithSecretSauce('Me') );
And even
// It even takes care to return the thunk’s return value // from the dispatch, so I can chain Promises as long as I return them. store.dispatch( makeASandwichWithSecretSauce('My wife') ).then(() => { console.log('Done!'); });
Here a complete example on how you can write action creators that dispatch actions and async actions from other action creators, and build your control flow with Promises.
function makeSandwichesForEverybody() { return function (dispatch, getState) { if (!getState().sandwiches.isShopOpen) { // You don’t have to return Promises, but it’s a handy convention // so the caller can always call .then() on async dispatch result. return Promise.resolve(); } //Do this action before starting the next one below dispatch(simple_action()); // We can dispatch both plain object actions and other thunks, // which lets us compose the asynchronous actions in a single flow. return dispatch( makeASandwichWithSecretSauce('My Grandma') ).then(() => Promise.all([ dispatch(makeASandwichWithSecretSauce('Me')), dispatch(makeASandwichWithSecretSauce('My wife')) ]) ).then(() => dispatch(makeASandwichWithSecretSauce('Our kids')) ).then(() => dispatch(getState().myMoney > 42 ? withdrawMoney(42) : apologize('Me', 'The Sandwich Shop') ) ); }; } //apologize and withdrawMoney are simple action like this for example return { type: "END_SUCESS" }
//usage
store.dispatch( makeSandwichesForEverybody() ).then(() => console.log("Done !"); );
To create you own promises you can use a library like bluebird.
//EDIT : To be sure that the store has processed that action completely before anything else happens in the function action_creator() you can dispatch this simple_action before action_creator(); // I added this comment to the code //Do this action before starting the next one below
This is a pattern I've been using recently:
export const someThenableThunk = someData => (dispatch, getState) => Promise.resolve().then(() => { const { someReducer } = getState(); return dispatch({ type: actionTypes.SOME_ACTION_TYPE, someData, }); });
When you dispatch(someThenableThunk('hello-world'))
, it returns a Promise
object that you can chain further actions to.
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