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;
};
};
}
Ok I'll bite. Let's start from the basics.
This redux middleware, wired up inside createStore.js. It gets run everytime we invoke a redux action.
There are other middlewares as well that always gets run on each redux action. It's up to each middleware to determine whether or not it wants to respond to the action.
Now let's get to the code you asked about.
What is it trying to do overall?
The middleware executes an ajax request and runs a particular redux action if it is successful or another particular redux action if the ajax request fails.
The code for the middleware is looking for an action being invoked with an object that has the following properties:
types -- Expected to be an array of 3 objects. It assumes the first object is a request, the second object is a function to invoke when the request succeeds, and the third object is a function to invoke if the request fails.
promise -- a function to be executed that returns a promise
How does it do this? Let's walk through the code, I've added my comments as // Comment JDO:.
return ({dispatch, getState}) => { ===>
**// Comment JDO: If the action is a function then please move on to the next action. This
middleware is looking for an object**
return next => action => {
if (typeof action === 'function') {
return action(dispatch, getState);
}
** // Comment JDO: If the action does not have a promise please move on to the next middleware. This middleware needs a promise to act on **
const { promise, types, ...rest } = action;
if (!promise) {
return next(action);
}
** // Comment JDO: This is where the real work takes place. An action has been invoked that has type
being an object and has a property called promise. **
** // Comment JDO: The types property is expected to be an array. We use the first element as REQUEST, the second element as SUCCESS and the third element as FAILURE **
const [REQUEST, SUCCESS, FAILURE] = types;
next({...rest, type: REQUEST});
** // Comment JDO: Invoke the promise passing the apiClient. On success execute the SUCCESS function (second param of types above), If it returns failure then invoke the FAILURE function (third param of types above)**
const actionPromise = promise(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;
};
};
So let's look at how it's used. For instance in widgets.js
export function save(widget) {
return {
types: [SAVE, SAVE_SUCCESS, SAVE_FAIL],
id: widget.id,
promise: (client) => client.post('/widget/update', {
data: widget
})
};
}
When you invoke the save action above, it passes an object to redux which gets passed to each middleware. The object has a types property, an id property and a promise property which takes in a client object.
If you remember our clientMiddleware discussion above, this is exactly the kind of object our middleware is coded to respond to.
It splits the types property into 3 parts:
It then invokes the promise. In our case the promise is:
promise: (client) => client.post('/widget/update', {
data: widget
})
So this code causes a post request to be issued and if it succeeds it invokes the SAVE_SUCCESS action and if it fails it invokes the SAVE_FAIL action.
It's a lot to take in so feel free to ask questions.
Most helpful comment
Ok I'll bite. Let's start from the basics.
This redux middleware, wired up inside createStore.js. It gets run everytime we invoke a redux action.
There are other middlewares as well that always gets run on each redux action. It's up to each middleware to determine whether or not it wants to respond to the action.
Now let's get to the code you asked about.
What is it trying to do overall?
The middleware executes an ajax request and runs a particular redux action if it is successful or another particular redux action if the ajax request fails.
The code for the middleware is looking for an action being invoked with an object that has the following properties:
types -- Expected to be an array of 3 objects. It assumes the first object is a request, the second object is a function to invoke when the request succeeds, and the third object is a function to invoke if the request fails.
promise -- a function to be executed that returns a promise
How does it do this? Let's walk through the code, I've added my comments as // Comment JDO:.
So let's look at how it's used. For instance in widgets.js
When you invoke the save action above, it passes an object to redux which gets passed to each middleware. The object has a types property, an id property and a promise property which takes in a client object.
If you remember our clientMiddleware discussion above, this is exactly the kind of object our middleware is coded to respond to.
It splits the types property into 3 parts:
It then invokes the promise. In our case the promise is:
So this code causes a post request to be issued and if it succeeds it invokes the SAVE_SUCCESS action and if it fails it invokes the SAVE_FAIL action.
It's a lot to take in so feel free to ask questions.