Real life React Higher Order Component use case (withLoading)

Higher Order Components in React are considered an advanced React topic.
I will try to simplify it and show one real life example that we will hopefully use (or base on it) in real life.

Let’s consider our day to day task which is to fetch data from somewhere and display them in the UI. We also need to handle errors and show loader messages to the user. This article will focus on the loader component.

For the sake of this exercise we will consider two approaches:

  • in the first approach we will handle loader in the component
  • in the second approach we will use Higher Order Component

You can see the example code in the sandbox and here is the GitHub repository.

First things first

Let’s create a new React app with:

npx create-react-app hoc-demo

Then we can open our IDE and start the terminal.

Our <List/> component looks similar to below:

import React from "react";
export const List = ({ data }) => { if (!data) return null; if (!data.length) return <p>No data</p>; return ( <ul> {data.map((item) => { return <li key={item.id}>{item.name}</li>; })} </ul> );};

We have basic error handling in here which should cover most of the cases:

if (!data) return null;if (!data.length) return <p>No data, sorry</p>;

Going forward at this point we are sure that we have some data in our data array. We can proceed with basic HTML list to display the data:

return (  <ul>    {data.map((item) => {      return <li key={item.id}>{item.full_name}</li>;     })}  </ul>);

It’s a very simple component to be shown when we fetch the data.

import React from "react";export const Loader = () => {  return <p>Fetching the data</p>;};

Handling loader state in the component

One of the popular approaches is to handle loading states directly in the component i.e.

import React from "react";
import { Loader, List } from 'components';
const ExampleComponent = ({ data, isLoading }) => { return isLoading ? <Loader/> : <List data={data} />;};

This is very simple solution utilising ternary operator. It works, is battle proven and sometimes it’s exactly what we need.

It does not however scale very well if we need similar behaviour in lot’s of different places.

To counter that we can introduce Higher Order Component pattern.

withLoading Higher Order Component

For the sake of this exercise our Higher Order Component is very basic so that we get the feeling of it:

import React from "react";/*** HOC to handle loading states.* Returns passed component or loader component/message** @param  {*} Component*             Component to be displayed if the loading is finished** @return {*} Component to be displayed or loading message   **/function WithLoading(Component) {  return function WithLoadingComponent({ isLoading, ...props }) {    if (!isLoading) return <Component {...props} />;       return <p>Fetching data...</p>;    };}export default WithLoading;

We can then use it:

import React from "react";
import { List } from 'components';
import WithLoading from "hoc";
// calling our HOCconst ListWithLoading = WithLoading(List);const ExampleComponent = ({ data, isLoading }) => { return <ListWithLoading isLoading={isLoading} data={data} />;};

Now we no longer have to worry about conditionally handling loader in the component. This part of the code is definitely reusable.

We could extend our HoC to handle custom loading message with help of a parameter i.e.

import React from "react";import { Loader } from "components";/*** HOC to handle loading states.* Returns passed component or loader component/message* * @param  {*} Component*             Component to be displayed if the loading is finished** @param  {*} LoaderComponent*             Component to be displayed during data fetching*             Defaults to Loader component* @return {*} Component to be displayed or loader component**/function WithLoading(Component, LoaderComponent = Loader) {  return function WithLoadingComponent({ isLoading, ...props }) {    if (!isLoading) return <Component {...props} />;      return <LoaderComponent {...props} />;    };   }export default WithLoading;

Now we can call it like so:

const ListWithLoading = WithLoading(List, CustomLoaderComponent);

or just

const ListWithLoading = WithLoading(List);

and the <Loader/> component would be used as a default one if second parameter is omitted.

This solution scales really well.

Summary

In this article I’ve presented basic, battle proven and justified use case of React HOC — withLoading.

Another interesting use case might be withAuthcomponent where we would protect our components based on some isAuthenticatedvalue.
That is a topic for another discussion however. :)

In my opinion, the HOC are not very advanced topic and definitely have useful use cases. It’s just they are often overengineered and misunderstood by the developers.

Just keep it simple and don’t create one for the sole purpose of creating one. You will know it when you need one.

Technical Lead. Seeking to make a change. Doing quality work that matters for people who care.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store