Search code examples
javascriptreduxredux-middlewareredux-loop

Why redux-loop actions skip all middlewares?


I run redux-loop official example with a little change:

  1. Instead of fetch I use promise with a timeout.
  2. I added log middleware (copy-paste from redux.js.org tutorial).

side-effect function:

import {createStore, compose, applyMiddleware} from 'redux';
import {install, loop, Cmd} from 'redux-loop';

function fetchUser(userId) {
    return Promise.resolve((res, rej) => setTimeout(() => res(userId), 1000));
}

Actions:

function initAction() {
    return {
        type: 'INIT'
    };
}

function userFetchSuccessfulAction(user) {
    return {
        type: 'USER_FETCH_SUCCESSFUL',
        user
    };
}

function userFetchFailedAction(err) {
    return {
        type: 'USER_FETCH_ERROR',
        err
    };
}

Initial state:

const initialState = {
        initStarted: false,
        user: null,
        error: null
    };

Reducer:

function reducer(state = initialState, action) {
        console.log(action);  // I added this line
        switch (action.type) {
            case 'INIT':
                return loop(
                    {...state, initStarted: true},
                    Cmd.run(fetchUser, {
                        successActionCreator: userFetchSuccessfulAction,
                        failActionCreator: userFetchFailedAction,
                        args: ['1234']
                    })
                );

            case 'USER_FETCH_SUCCESSFUL':
                return {...state, user: action.user};

            case 'USER_FETCH_FAILED':
                return {...state, error: action.error};

            default:
                return state;
        }
    }

My custom log middleware:

    const logger = store => next => action => {
        console.group(action.type);
        console.info('dispatching', action);
        let result = next(action);
        console.log('next state', store.getState());
        console.groupEnd();
        return result
    };

Configure store:

const enhancer = compose(
        applyMiddleware(logger),
        install()
    );

    const store = createStore(reducer, initialState, enhancer);

Dispatching the first action to start it all: (my code)

store.dispatch(initAction());

output:

enter image description here


As you can see, the second action skipped my log middleware and also the last line of the log is not clear to me. Why the reducer received a function instead of the actual user object?


Solution

  • Why the reducer received a function instead of the actual user object?

    return Promise.resolve((res, rej) => setTimeout(() => res(userId), 1000));
    

    Promise.resolve is used to create a promise already in the resolved state. It expects you to pass in what value the promise should resolve with, and in your case, you've asked it to resolve to a function.

    You probably meant to do:

    return new Promise((res, rej) => setTimeout(() => res(userId), 1000))