Search code examples
asynchronousreduxmiddleware

What's the functionality of redux middleware actions


A middleware in Redux is defined by the signature

const middleware = store => next => action => {}

What is the definition of action and how are they supposed to be created?

I wanted to create a new middleware for handling async actions, where actions could contain instructions for the side effect to exectute and also the action to dispatch on success. I set up my middleware as follows:

const effectMiddleware = store => next => async (action) => {
    // Assert it's actually a command
    if (action.command !== undefined) {
        next(action)
        const result = await Cmd.execute(action.command) // returns a redux action
        return store.dispatch(result)
    else {
        next(action)
    }
}

However, I was running into strange errors where the next action would not be executed. I discovered that in fact middleware "actions" are not the same action as the ones you define in your application. Using console log I discovered that action in middlewares is actually

action: Object { type: "MY_ACTION", payload: {} }
​
stack: undefined
​
timestamp: 1571214156244
​
type: "PERFORM_ACTION"

Hence why it did not execute the action returned by Cmd.execute. I managed to get around this by creating a wrapAction function:

const wrapAction = (action) =>
    ({ action: action, type: "PERFORM_ACTION", stack: undefined, timestamp: new Date().valueOf() })

const effectMiddleware = store => next => async (action) => {
    // Assert it's actually a command
    if (action.action.command !== undefined) {
        next(action)
        const result = await Cmd.execute(action.action.command) // Cmd.execute returns a Promise<redux action>
        return store.dispatch(wrapAction(result))
    else {
        next(action)
    }
}

However, I can not find the documentation for this anywhere and so my question is: how is the middleware actually meant to be used? What's the official way to "wrap" actions into these middleware actions?


Solution

  • The reason this happens is because of redux devtools! When you use multiple middlewares redux devtools always needs to be last.