React
Performing HTTP Requests with Custom Middleware
  •  

Creating Promise Middleware

PRO

The first thing we'll do is integrate our agent file with the Home component:

Integrate with Home component
import Banner from './Banner';
import MainView from './MainView';
import React from 'react';
import agent from '../../agent';
import { connect } from 'react-redux';

const Promise = global.Promise;

const mapStateToProps = state => ({
  appName: state.appName
});

const mapDispatchToProps = dispatch => ({
  onLoad: (payload) =>
    dispatch({ type: 'HOME_PAGE_LOADED', payload }),
});

class Home extends React.Component {
  componentWillMount() {
    this.props.onLoad(agent.Articles.all());
  }

  render() {
    // ...
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Home);

This mapDispatchToProps function is the second function that gets passed to react-redux's connect() function. The mapDispatchToProps() function maps the Redux store's dispatch() function to functions. Each function that mapDispatchToProps() returns gets attached to the component's props. This means your component can call this.props.onLoad() to fire off an event with type 'HOME_PAGE_LOADED' and a 'payload'. This payload will contain the HTTP promise.

The right place to call the promise is in the componentWillMount() function. This componentWillMount() function is what's known as a "lifecycle hook" It'll get called when this component gets created, so let's put the initialization logic here.

Great, so now you're dispatching an action that has a 'payload' property that contains a promise. Redux has a concept called "middleware", which lets you intercept and transform actions. Let's write some middleware that'll intercept actions where the 'payload' property is a promise.

Create the promise middleware
const promiseMiddleware = store => next => action => {
  if (isPromise(action.payload)) {
    action.payload.then(
      res => {
        action.payload = res;
        store.dispatch(action);
      },
      error => {
        action.error = true;
        action.payload = error.response.body;
        store.dispatch(action);
      }
    );

    return;
  }

  next(action);
};

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

export {
  promiseMiddleware
};

Great, now you need to plug this middleware into the redux store. Back in index.js, let's use this createMiddleware function that redux exports to plug the promise middleware into redux.

Apply the promise middleware to our store
import App from './components/App';
import { Provider } from 'react-redux';
import ReactDOM from 'react-dom';
import React from 'react';
import { applyMiddleware, createStore } from 'redux';
import { promiseMiddleware } from './middleware';

const defaultState = {
  // ...
};
const reducer = function(state = defaultState, action) {
  // ...
};
const store = createStore(reducer, applyMiddleware(promiseMiddleware));

// ...
 

I finished! On to the next chapter