Custom Redux Middleware - Dispatch to beginning of middleware chain?

后端 未结 1 1047
Happy的楠姐
Happy的楠姐 2021-01-20 07:42

I am writing a custom middleware that needs to dispatch thunk actions. The problem is that the middleware is called after redux-thunk in the middleware chain,

1条回答
  •  轮回少年
    2021-01-20 08:23

    Dispatching inside the middleware chain will send the action to the start of the middleware chain, and will call the thunk as usual (Demo - look at the console).

    Why?

    The original store.dispatch() (before applying middlewares) checks if the action is a plain POJO, and if not throws an error:

      function dispatch(action) {
        if (!isPlainObject(action)) {
          throw new Error(
            'Actions must be plain objects. ' +
            'Use custom middleware for async actions.'
          )
        }
    

    When you applyMiddleware() the dispatch is replaced by a new method, which is the chain of middleware, that call the original store.dispatch() in the end. You can see it in the applyMiddleware method:

    export default function applyMiddleware(...middlewares) {
      return (createStore) => (reducer, preloadedState, enhancer) => {
        const store = createStore(reducer, preloadedState, enhancer)
        let dispatch = store.dispatch // dispatch is now the original store's dispatch
        let chain = []
    
        const middlewareAPI = {
          getState: store.getState,
          dispatch: (action) => dispatch(action) // this refers to the dispatch variable. However, it's not the original dispatch, but the one that was created by compose
        }
        chain = middlewares.map(middleware => middleware(middlewareAPI))
        dispatch = compose(...chain)(store.dispatch) // dispatch is a composition of the chain, with the original dispatch in the end
    
        return {
          ...store,
          dispatch
        }
      }
    }
    

    btw - change your middleware to this, since the 1st function will prevent your middleware from working.

    export default const createMiddleware = ({dispatch, getState}) => next =>   (action) => {
        if(action.type !== 'FOO') {
            return next(action);
        }
    
        dispatch(thunkActionHere); // this is the issue
    }
    

    0 讨论(0)
提交回复
热议问题