1. 程式人生 > >Middlewares And React Redux Life Cycle

Middlewares And React Redux Life Cycle

Middlewares And React Redux Life Cycle

If you have built Node.js apps using frameworks like Express.js, you are probably aware of functions called “middlewares” and how they work. Redux brings that same concept to the front-end.

What are Middlewares?

Middlewares are functions that are automatically called by the framework(Redux in our case) somewhere in the middle of the supposed control flow to enhance or change the output, before the end of the control flow.

For example: If the framework’s usual control flow without middleware is:

funcA — callsfuncB — callsfuncC

When the middlewares are added, the control flow may look like:

funcA — callsfuncB — calls funcMiddleWare1 —back to →funcB. funcBthen calls funcMiddleWare2 — back tofuncB. funcB — finally

callsfuncC

Notice that funcB ultimately calls funcC but calls two middlewares before calling funcC.

Redux Life Cycle w/ And w/o Middlewares

Let’s take a look at Redux app life cycle (control flow) to understand it better.

Scenario: Clicking on the “Click Me” button, updates the “Clicked xyz times” text.

Note: You can click on the pictures to Zoom and read

Scenario: Now, let’s say when the user clicks the button, we want to save click count to the server and also do console logs of state changes for debugging. We could use middlewares! Let’s see how the control flow looks now.

In Redux, middleware functions are called one-by-one until all of them are called and then the “Action” object is sent to the “Reducers”.

Note: This is to allow middlewares to potentially modify Action object, resolve AJAX calls, and do other things like logging, before finally calling reducers. Reducers will then update state and rerender the app if needed.

Using Middlewares

Redux has a huge community that has built up massive number of middleware functions that do all sorts of things.

All you need to use it is:

  1. Install it via npm and
  2. Configure or add it to Redux.

For example: In my previous blog:A Guide For Building A React Redux CRUD App , the app makes an AJAX request for CRUD operations.

In that, I use a library called Axiosto make the AJAX calls. But Axios returns a Promise in return. But Actions need to be pure JSON object with all the data before it reaches Reducers. So, I ended upusing redux-promiseto intercept anytime the “Action” contains a Promise object and resolve it before the control hits the Reducers.

In order to use that first I had to install

npm install — save redux-promise

Then configure it to Redux like below:

import React from ‘react’;
...
import { createStore, applyMiddleware } from ‘redux’;
import rp from ‘redux-promise’; // <------------ MIDDLEWARE
...
//add middlewares
const createStoreWithMiddleware = applyMiddleware(rp)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<Router history={browserHistory} routes={routes} />
</Provider>
, document.getElementById(‘body’));

How does a Middleware Work?

If you look at the redux-promise’ source code, you’ll see how it looks and works.

Here is the pseudo code.

  1. Redux calls middleware w/ , “dispatch”(function) and “next”(function) and the “action” JSON object.

2. Middleware inspects “action” object to see if it has a Promise.

3. If there are no Promise, then it calls “next” function to return control back to Redux.

4 If it does, then it attaches(chains) it’s own success and a failure callbacks and waits for the response from the server.

4.1 And once the Promise is resolved, it finally calls “dispatch” function to return result or error(from the server) and sends it back to Redux.

//redux-promise middleware source code
import { isFSA } from 'flux-standard-action';

function isPromise(val) {
return val && typeof val.then === 'function';
}

export default function promiseMiddleware({ dispatch }) {
return next => action => {
if (!isFSA(action)) {
return isPromise(action)
? action.then(dispatch)
: next(action);
}

return isPromise(action.payload)
? action.payload.then(
result => dispatch({ ...action, payload: result }),
error => dispatch({ ...action, payload: error, error: true })
)
: next(action);
};
}

Learn more:

That’s it!

My Other Blogs

ES6

WebPack

Draft.js

React And Redux :

Salesforce