Implementing redirect in Redux middleware Let's say I have following action:

export function signIn(data) {
  return {
    type: USER_SIGN_IN,
    promise: api.post('/sign_in', data)
  }
}


and the following middleware:

export default function promiseMiddleware() {
  return next =&gt; action =&gt; {
    const { promise, type, ...rest } = action

    if (!promise) {
      return next(action)
    }

    const SUCCESS = `${type}_SUCCESS`
    const REQUEST = `${type}_REQUEST`
    const ERROR = `${type}_ERROR`

    next({ ...rest, type: REQUEST })

    return promise
      .then(res =&gt; {
        next({ ...rest, response: res.data, type: SUCCESS })
        return true
      })
      .catch(error =&gt; {
        next({ ...rest, response: error.response.data, type: ERROR })
        return false
      })
  }
}


This code is loosely based on https://github.com/reactGo/reactGo/

But what if in then callback after calling next I want to make a redirect to another path?

I did following. I passed redirect url through action:

export function signIn(data) {
  return {
    type: USER_SIGN_IN,
    promise: api.post('/sign_in', data),
    redirect: '/'
  }
}


and added another call of next method with push from react-router-redux:

import { push } from 'react-router-redux'

export default function promiseMiddleware() {
  return next =&gt; action =&gt; {
    const { promise, type, redirect, ...rest } = action

    if (!promise) {
      return next(action)
    }

    const SUCCESS = `${type}_SUCCESS`
    const REQUEST = `${type}_REQUEST`
    const ERROR = `${type}_ERROR`

    next({ ...rest, type: REQUEST })

    return promise
      .then(res =&gt; {
        next({ ...rest, response: res.data, type: SUCCESS })
        next(push(redirect))
        return true
      })
      .catch(error =&gt; {
        next({ ...rest, response: error.response.data, type: ERROR })
        return false
      })
  }
}


It seems like it works, but I'm not sure if this is a good idea or if there are some pitfalls of multiple next calls and I shouldn't do like this? Or maybe I should use dispatch method which I can get from promiseMiddleware params instead of next for redirecting?

If there are some better approaches for implementing such redirects, please, let me know.
Instead of creating your custom promiseMiddleware you could use the redux-thunk middleware which accepts a function as an action. And the function will be called with dispatch and getStore as parameters.

Imagine you would like to fetch some data.. and you want to do it as an action. like dispatch(getPost(id))

normally your actionCreator getPost would return the action object, 

const getPost = (id) =&gt; {
  return {
    type: "FETCH_POST",
    id
  }
}


But when you use redux-thunk you can return a function:

const getPost = (postId) =&gt; {
  return dispatch =&gt; {
      // Now you can use dispatch inside this block, even for async calls..
      // Start fetching.. 
      dispatch({type: "START_LOADING_POST" }) // imagine this could change your state to {isLoading: true}

      http
       .get("from.somewhere.net/post/" + postId)
       .then((data) =&gt; dispatch({type: "POST_LOADED_SUCCESS", postId, data }))
       .catch((error) =&gt; dispatch(loadingPostFailed({postId, error})))
  }
}


I think you know how to apply the middleware to the store, so I skip it. Hope it makes it clear how you can extend your actionCreators with redux-thunk to functions and use them specially for async tasks, like promises or even with callback-based libraries.

Redux thunk was part of redux, but its now an own package, but also maintained by Dan Abramov, check out the repo: https://github.com/gaearon/redux-thunk

If you would like to save some time by writing every actionCreator by hand you could create an creator for the actionCreator :D sounds funny, but take a look at this:

const promiseActionCreator = type =&gt; {
   const
      start    = type + "_START",
      resolved = type + "_RESOLVED",
      failed   = type + "_FAILED";

   return (params) =&gt; (dispatch, getState) =&gt; {

      dispatch({type: start})

      http
          .get(params.url)
          .then(result =&gt; dispatch({type: resolved, result }))
          .catch(error =&gt; dispatch({type: failed, error }))
   }
}

// Now you can create/generate your special promise based actionCreator
const getPost = promiseActionCreator("POST_LOADER");