7

I use redux-actions and redux-promise-middleware to dispatch actions, along with TypeScript 2.1 for async await support.

This is an action using both redux-actions and redux-promise-middleware

// create an async action
const fooAction = createAction('FOO', async () => {
  const { response } = await asyncFoo();
  return response;
});

// use async action
fooAction('123')

And this is an example of action chaining, using only redux-promise-middleware

const foo = () => dispatch => {
  return dispatch({
    type: 'TYPE',
    payload: new Promise()
  })
  .then(() => dispatch(bar()));
}

How chaining in redux-promise-middleware can be used together with redux-actions?

Preview
  • 35,317
  • 10
  • 92
  • 112
Rajab Shakirov
  • 7,265
  • 7
  • 28
  • 42
  • After 5 months of using this on a real project, I switched to redux-saga. The problem with redux-thunk is that you have to transfer more and more data as parameters to the actions, and in the end, you want to transfer the entire state of the application there. Redux-saga knows this by default and has special methods for this and other useful things. – Rajab Shakirov Jun 11 '17 at 12:09
  • 1
    BTW with thunks you can also read the state with getState. The signature is (dispatch, getState) => ... – Edgar Villegas Alvarado May 29 '18 at 15:55

2 Answers2

5

You have to keep in mind that even if async await looks synchronous, it uses Promises under the hood, and an async function will always return a Promise, no matter if you use await or not.

Since the second parameter of createAction is your payload creator, nothing can stop you from using the resulting object.

Here is an example based on your initial code:

const fakeCall = () => new Promise(resolve => {
  setTimeout(() => resolve({ response: 'ok' }), 1E3)
})

const fooAction = createAction('FOO', async () => {
  const { response } = await fakeCall()
  return response
})

const foo = () => dispatch =>
  dispatch(fooAction())
    .then(() => dispatch(bar()))

// or

const foo = () => async dispatch => {
  await dispatch(fooAction())
  dispatch(bar())
}
Preview
  • 35,317
  • 10
  • 92
  • 112
-1

The problem with Aperçu answer is that "await" is you are Blocking the event loop and you have to handle the Promises directly.

There is an alternative to "redux-promise-middleware", redux-auto have the same API as redux-promise-middleware but also come with a mechanism to chaining reducers calls.

Your example would look something like:

// UI code
actions.data.foo()

// store/data/foo.js
export function fulfillment(data,payload){
   return data
} fulfillment.chain = actions.x.bar

export function action(payload){
    return Promise.resolve()
}

Really, thats it. You only need to assign the action to a chain property and redux-auto will call it at the right point in the redux life-cycle

To understand the above source. redux-auto automatically create actions and wires them to reduces based on the file structure. Where the folder name becomes the name of the property on the state. The files within a folder are actions to be performed on that part of the state.

Here is the documentation chaining action together

Brian
  • 1,026
  • 1
  • 15
  • 25
  • You should disclose that redux-auto is your library when advertising it in your answers. – Preview Oct 30 '17 at 18:51
  • 1
    await doesn't block the event loop. It just looks synchronous just like Aperçu said. Stuff like click events etc. in your app still work. `while true` would block the event loop – mop Apr 30 '18 at 09:44