Creating A Higher Order Fetch Component To Create A Cleaner React Code Base

If you need to call a lot of API'S in your React app and Redux or React hooks seem a bit of an overkill for your project, then read on.  In this tutorial, you will learn how to refactor your React components into higher order components that will maximize reuse.  One of the key aims of any software developer who wants to write good code is to avoid writing unneeded code, this is known as the DRY principle.  If you are writing lots of async code all over your app then you are breaking this. 

This tutorial assumes that you have read How To Call An API In Your React Component.  The aim of this article is to show you how you can write more reusable components.  The code in here is more geared for demonstrating principles, rather than production ready code you can simply copy and paste.. be warned!

Container and Presentational Pattern

When writing a React application, a good approach to try to follow when you write your code is the container and presentational pattern. This may sound fancy, but, what it really means is if you need to write a component that has some logic in it. Instead of writing one component, try to break it into two. One that does the logic, then another really simple, dumb component that does the rendering. Getting data from an API and rendering it, is a great example of where the container and presentational pattern can be applied.

Instead of writing one component, that does everything, we write two. One to get the data. This component can then re-used so we don't have to write the fetch code ever again. The second that renders the HTML, so let's get cracking.

Higher Order Components

Let's start with some code:

const withData = url => WrappedComponent =>
  class extends React.Component {
    constructor(props) {
       super(props)
       this.state = { 
           data: {},
           isFecthing: true;
       }
    }

    componentWillMount() {
        fetch(url)
         .then(function(response) {
            return response.text()
          }).then(data => {
                 this.setState({data, isFecthing:false);
          })
  })

    render() {
      const { isFetching } = this.props;
      if (isFetching) return <div>Loading</div>;
      return <WrappedComponent {...this.props} {...this.state};
    }
  };

export default withData;

The component above is a wrapper.  It contains no presentation code itself.  In render, all we do is either display a message if the data is still loading, or it will render the WrappedComponent that is passed in. 

Using this technique, instead of writing all our code in one massive component, we've abstracted it, into withData.  The component uses currying to pass in two arguments, the URL for the API and a component to wrap it.  We use currying to make the calling code a little simpler (we'll get back to this later).  In componentWillMount, fetch is used to get the data from the API.  On a successful return, a property in a state called data is set and isFetching is set to false. Render() will now be recalled.  WrappedComponent will be called, with all the props and state the wrapper got passed.  This is a classic example of functional programming.  

To render some HTML on the page, a second presentation component needs to be written.  TO display our data in a UL, we could write something like this:

const List = ({data: myList}) => (
       <ul>
         {myList.map)(item => ( <li key=item.id">item.value</li>
      </ul>
})}

Using this approach, our two components are simpler than the original code in How To Call An API In Your React Component. We now have a very simple UI component. It has no clue to the data it uses and it should not care.  This component is also a stateless component, which simplifies our code.

To render the complete HTML, we now write:

const WithAPIResponse = withData('http://MY-API-URL');
const ListWithAPIResponse = WithAPIResponse(List);

As I'm hoping you can now appreciate, we have simplified our code.  We've created a component 'withData' we can re-use all over our codebase to pass API data into a component.  We've also created a super simple, stateless presentation component to render out the list.  This component is now really simple to test.  It can also be more easily re-used.

Summary

If you consistently apply this approach, you will end up with lots of smaller reusable components. You will get more re-use and your components will become a lot easier to test. All in all.. a big win! There are others to further enhance this component.

submit to reddit

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

Back to top