💫
Promise Middleware
  • Introduction
  • Getting Started
    • Introduction
    • Design Principles
  • Guides
    • Catching Errors Thrown by Rejected Promises
    • Chaining Actions
    • Comparison to other promise middleware
    • Custom Type Delimiters
    • Custom Types
    • Optimistic Updates
    • Use with Async/Await
    • Use with Reducers
    • Use with Redux Actions
    • Use with Redux Promise Actions
    • Use with Promises Resolved with Null Values
  • Upgrade Guides
    • Upgrade from 5.x to 6.0.0
    • Upgrade from 4.x to 5.0.0
    • Upgrade from 3.x to 4.0.0
    • Release History
Powered by GitBook
On this page
  1. Guides

Chaining Actions

PreviousCatching Errors Thrown by Rejected PromisesNextComparison to other promise middleware

Last updated 5 years ago

When a promise is resolved, one might want to dispatch additional actions in response. One example could be changing the route after a user is successfully signed in. Another could be showing an error message after a request fails.

First, note this behavior uses thunks. You will need to include in your middleware stack.

Note: Redux Thunk is a middleware that enables action creators to return a function instead of an object (). The returned function is called with a dispatch argument, which is what you can use to chain actions.

const foo = () => {
  return dispatch => {

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

If you need to chain several actions, using Promise.all is suggested.

const foo = () => {
  return dispatch => {

    return dispatch({
      type: 'TYPE',
      payload: Promise.all([
        dispatch(bar()),
        dispatch(baz())
      ])
    });
  };
}

When handling a promise with then, the parameter is an object with two properties: (1) the "value" (if the promise is fulfilled) or the "reason" (if the promise is rejected) and (2) the object of the dispatched action.

// fulfilled promise
const foo = () => {
  return dispatch => {

    return dispatch({
      type: 'FOO',
      payload: new Promise(resolve => {
        resolve('foo'); // resolve the promise with the value 'foo'
      })
    }).then(({ value, action }) => {
      console.log(value); // => 'foo'
      console.log(action.type); // => 'FOO_FULFILLED'
    });
  };
}

// rejected promise
const bar = () => {
  return dispatch => {

    return dispatch({
      type: 'BAR',
      payload: new Promise(() => {
        throw new Error('foo'); // reject the promise for the reason 'bar'
      })
    }).then(() => null, error => {
      console.log(error instanceof Error) // => true
      console.log(error.message); // => 'foo'
    });
  };
}

Rejected promises can also be handled with .catch().

// rejected promise with throw
const baz = () => {
  return dispatch => {

    return dispatch({
      type: 'BAZ',
      payload: new Promise(() => {
        throw new Error(); // throw an error
      })
    }).catch((error) => {
      console.log(error instanceof Error) // => true
    });
  };
}
Redux Thunk
hence the name "thunk"