Shubham
Shubham

Reputation: 1201

How dispatch is accessible in redux middleware?

I was exploring more about the redux middleware. But stuck on the point, where I don't understand how the 'dispatch' is accessible in redux middleware? Is it due to the createStore function? (at the time of initialization)

function createThunkMiddleware(extraArgument) {
  console.log('createThunkMiddleware =================', extraArgument)
  // console.log('dispatch =================', dispatch)
  return ({ dispatch, getState }) => next => action => {
    console.log('just above dispatch', dispatch)
    if (typeof action === 'function') {
      console.log('dispatch ======>',dispatch)
      console.log('action =====>',action)
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

Upvotes: 4

Views: 869

Answers (2)

Vijay Dev
Vijay Dev

Reputation: 1114

It's all about curry functions and closures. The middleware function you provide is internally mapped called via compose while the getstate and dispatch are passed as an argument object. The following code from redux code should be helpful: https://github.com/reactjs/redux/blob/master/src/applyMiddleware.js#L30-L40

let chain = []

const middlewareAPI = {
  getState: store.getState,
  dispatch: (...args) => dispatch(...args)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)

return {
  ...store,
  dispatch
}

As you can see "chain" is the mapped array of function with the getstate and dispatch object as argument. Hope this helps you to understand how the middleware works

Upvotes: 3

G4bri3l
G4bri3l

Reputation: 5146

If you take a quick look at the source you will see that it's the applyMiddleware function that injects the middleware API into each middleware.

export default function applyMiddleware(...middlewares) {
  return createStore => (...args) => {
    const store = createStore(...args)
    let dispatch = () => {
      throw new Error(
        `Dispatching while constructing your middleware is not allowed. ` +
          `Other middleware would not be applied to this dispatch.`
      )
    }
    let chain = []

    const middlewareAPI = {
      getState: store.getState,
      dispatch: (...args) => dispatch(...args)
    }

    // Here is the interesting part where we pass in the dispatch
    // and getState functions
    chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

This is directly from the redux source code linke here!. I could go into more details but I actually wrote about this here, so check it out as I go into details about this exact question. I hope this helps, let me know if you have other questions!

Upvotes: 4

Related Questions