stackjlei
stackjlei

Reputation: 10035

how does dispatch, next, and the ordering of middleware work in react redux?

I'm learning about middleware and want to confirm something. If I have the below middleware setup:

dispatch -> thunk -> promise middleware -> traffic middleware -> reducer

I want to clarify a few other things. Please let me know if my understanding of the below is incorrect:

  1. If I dispatch anything other a function, or promise, the action will go directly to the reducer.

  2. If I dispatch a function, it will go through thunk, and out of that function, if I call next, it will go through the promise middleware.

  3. If I dispatch a function, it will go through thunk, and out of that function, if I dispatch another function, it will go through thunk again, or it will go through promise middleware if I'm dispatching a promise.
  4. If I'm in the traffic middleware, calling next would take the action to the reducer, or if I called dispatch and the action is neither a function nor promise, it will also go directly to the reducer.
  5. If in thunk, promise middleware, or traffic middleware, I don't use dispatch or next, then the returned object is cut off and the cycle stops there and data will no longer go through any of the middleware chain nor to the reducer.

my middlewares.js

import * as actions from '../actions/actionCreators'
import { formatPokemonData, formatDescription, formatPokeType } from '../helpers/helpers'
import fetch from 'isomorphic-fetch'

export const promiseErrorMiddleware = store => next => action => {
  if (!action.promise) {
    return next(action)
  }
  const url = action.url
  const fetchName = action.fetchName
  return Promise.resolve(fetch(url)).then((response) => {
    if (response.status === 404) {
      store.dispatch({type: 'SPELLING_ERROR'})
      throw new Error("Please ensure Pokemon name is spelled correctly")
    } else if (response.status >= 400) {
      store.dispatch({type: 'SERVER_ERROR'})
      throw new Error("Server Error")
    }
    return response.json()
  }).then((data) => {
    next({data: data, needDirection: true, fetchName: fetchName })
  })
}

export const dataTrafficMiddleware = store => next => action => {
  if (!action.needDirection) {
    return next(action)
  }
  const data = action.data
  const fetchName = action.fetchName
  if (fetchName === 'fetchPokemon') {
    next(actions.receivePokemon(formatPokemonData(data)))
    store.dispatch(actions.fetchPokemonDescription(data.name))
  } else if (fetchName === 'fetchPokemonDescription') {
    store.dispatch(actions.receivePokemonDescription(formatDescription(data)))
    store.dispatch(actions.addActivePokemon(store.getState().pokemonArray.filter((p) => (
      p.name === data.name
    ))[0]))
    store.dispatch(actions.checkPokeTypeCache(store.getState().activePokemon.pokeType))
  } else if (fetchName === 'mainTypeFetch') {
    store.dispatch(actions.receivePokeType(formatPokeType(data)))
    store.dispatch(actions.addActivePokeType(formatPokeType(data)))
  } else if (fetchName === 'subTypeFetch') {
    store.dispatch(actions.receivePokeType(formatPokeType(data)))
    store.dispatch(actions.addActiveSubPokeType(formatPokeType(data)))
  }
}

Upvotes: 2

Views: 1532

Answers (1)

just-boris
just-boris

Reputation: 9776

  1. If I dispatch anything other a function, or promise, the action will go directly to the reducer.
  2. If I dispatch a function, it will go through thunk, and out of that function, if I call next, it will go through the promise middleware.

You are correct in these two points.

  1. If I dispatch a function, it will go through thunk, and out of that function, if I dispatch another function, it will go through thunk again

redux-thunk injects dispatch in the function, which starts process again from the start of chain. So, if you will put a function to dispatch, it will be handled by thunk again.

  1. If I'm in the traffic middleware, calling next would take the action to the reducer, or if I called dispatch and the action is neither a function nor promise, it will also go directly to the reducer.

It is hard to answer to you question, because I don't know your traffic middleware implementation

  1. If in thunk, promise middleware, or traffic middleware, I don't use dispatch or next, then the returned object is cut off and the cycle stops there and data will no longer go through any of the middleware chain nor to the reducer.

Yes, if you will not call next, the further middlewares in chain will not get your action, and there will be no any effect.

Upvotes: 2

Related Questions