user1820017 user1820017 - 2 days ago 6
React JSX Question

Can anyone explain what does middleware does in this example https://github.com/erikras/react-redux-universal-hot-example

Can anyone explain what does middleware does in this example https://github.com/erikras/react-redux-universal-hot-example/
It does not support real api requests?

export default function clientMiddleware(client) {
return ({dispatch, getState}) => {
return next => action => {
if (typeof action === 'function') {
return action(dispatch, getState);
}
const { promise, types, ...rest } = action;
if (!promise) {
return next(action);
}
const [REQUEST, SUCCESS, FAILURE] = types;
next({...rest, type: REQUEST});
const actionPromise = promise(client);
console.log('client ');
console.log(client);
actionPromise.then(
(result) => next({...rest, result, type: SUCCESS}),
(error) => next({...rest, error, type: FAILURE})
).catch((error)=> {
console.error('MIDDLEWARE ERROR:', error);
next({...rest, error, type: FAILURE});
});

return actionPromise;
};
};
}

Answer

Before going to find out what the clientMiddleware does, you need to know the purposes of the following files:

src/helpers/ApiClient.js: a class with a set of helper methods to perform API calls

src/redux/create.js: this method receives an instance of ApiClient as parameter client this is the same parameter the clientMiddleware gets

Now the clietMiddleware, the working is commented in the code

// The clientMiddleware basically aims to intercept actions which performs API call
// and it controls the dispatch of SUCCESS/FAILURE actions based on response
export default function clientMiddleware(client) {
    return ({dispatch, getState}) => {
        return next => action => {
            // action creator is expected to return an object but
            // if we get a function instead, lets unwrap the top layer
            // by invoking the method and see if the action creator is inside
            if (typeof action === 'function') {
              return action(dispatch, getState);
            }

            // destructure properties from action object
            const { promise, types, ...rest } = action;

            // the middleware can work only if the Object returned by
            // the action creator has a key 'promise' which is assigned
            // a function that returns promise (essentially your API call)
            if (!promise) {
              // no 'promise' key? that means this action is not an API call
              // let's pass this action to next middleware
              return next(action);
            }

            // destructures elements from types array
            // REQUEST = types[0]
            // SUCCESS = types[1]
            // FAILURE = types[2]
            const [REQUEST, SUCCESS, FAILURE] = types;

            // Call next middleware with action.type = REQUEST
            // this will eventually get dipatched and the REQUEST reducer will get executed
            // Invokes a reducer just before the API call
            // a chance to set flags like 'loading': { ...state, loading: true }
            next({ ...rest, type: REQUEST });

            // as I said before 'promise' is a function we got by destructuring 'actions'
            // and that function receives instance of ApiClient as parameter
            // thus in turn a promise is returned and we are storing that to a variable here
            const actionPromise = promise(client);

            // as the name says, 'actionPromise'' is a JavaScipt promise, a 'then'able one.
            actionPromise.then(
                // on succesfull completion of the API call dispatch the SUCCESS action with result
                // from API response, any additional parameters required by the reducer goes in ...rest
                (result) => next({ ...rest, result, type: SUCCESS }),

                // similar to the success case, we dipatch the FAILURE action with error when API fails
                (error) => next({ ...rest, error, type: FAILURE })
            ).catch((error)=> {
                next({ ...rest, error, type: FAILURE });
            });

            return actionPromise;
        };
    };
}
Comments