Higher Order Components in React: Examples with Common Use-case Patterns
Tags: webdev, javascript, react, programming
Published: 2023-05-05 14:01:42

***Dead Simple Chat offers powerful*** [***Javascript Chat SDK and APIs***](https://deadsimplechat.com/javascript-chat-api-sdk) ***that you can use to easily add Chat functionality to your React Applications.***


In this blog post, we will learn what are Higher Order Components, and learn about common use-case patterns. We will also look at code examples of common use-case patterns using Higher Order Components.

* [What are Higher Order Components?](https://deadsimplechat.com/blog/higher-order-componets-in-react/#what-are-hocs-in-react)
    
* [Basic Example of HOC](https://deadsimplechat.com/blog/higher-order-componets-in-react/#basic-hoc-example)
    
* [Common Use Case Patterns of Higher Order Components](https://deadsimplechat.com/blog/higher-order-componets-in-react/#common-use-case-patterns-for-hocs)
    
    * [Management of State and Handling of Async Data](https://deadsimplechat.com/blog/higher-order-componets-in-react/#1-management-of-state-and-handling-of-async-data)
        
    * [Conditional Rendering: Authorization and Feature Toggle](https://deadsimplechat.com/blog/higher-order-componets-in-react/#2-conditional-rendering-authorization-and-feature-toggle)
        
    * [Translation and Language Switching](https://deadsimplechat.com/blog/higher-order-componets-in-react/#3-translation-and-language-switching)
        
    * [Error Boundary](https://deadsimplechat.com/blog/higher-order-componets-in-react/#4-error-boundary)
        
* [Naming Conventions](https://deadsimplechat.com/blog/higher-order-componets-in-react/#naming-conventions)
    
* [Conclusion](https://deadsimplechat.com/blog/higher-order-componets-in-react/#conclusion)
    

## What are HOCs in React?

Higher Order Components or HOC are basically functions that take a component as an argument and return a new component.

Higher Order Components are useful to abstract a shared logic used by many components.

Components in React allow code reuse and prevent code repetition.

But when you develop a React application it is not always straightforward to apply the [DRY principles](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) and you have to write repeated code in multiple components.

But by using HOCs you can reduce the repeated code, by encapsulating that logic into a Higher Order Component. We will look at some examples and patterns below.

***Dead Simple Chat offers powerful*** [***Javascript Chat SDK and APIs***](https://deadsimplechat.com/javascript-chat-api-sdk) ***that you can use to easily add Chat functionality to your React Applications.***

## Basic HOC Example

Let's look at a very basic example, to understand  Higher Order Components.

This is a very basic example and in the real world it will not make sense to encapsulate the logic into Higher Order Components but it would serve as a good example to understand Higher Order Components.

We will also look at examples and scenarios later in this blog post where to use Higher Order Components in real-world use cases.

Let's look at our example, we will create a React Component that upon hover its background color changes to blue.

```js
const TextComponent = ({ text }) => {
  const [isHovered, setHovered] = useState(false);

  function handleMouseEnter() {
    setHovered(true);
  }

  function handleMouseLeave() {
    setHovered(false);
  }

  return (
    <>
      <p
        style={{ backgroundColor: isHovered ? "blue" : "white" }}
        onMouseEnter={handleMouseEnter}
        onMouseLeave={handleMouseLeave}
      >
            { text }
      </p>
    </>
  );
};
```

We have created a simple React Componenet called as the `TextComponent` and when the mouse is hovered upon the `TextComponent` its background color changes to blue.

To achieve this we are using the `isHovered` variable and setting it to `true` on the `MouseEnter` event and then resetting it to `false` on `MouseLeave` event.

However, if we want to add this same functionality into other components in our application, then we would have to repeat the same code, again in the other components.

To prevent this we can wrap the logic to detect the hover in a Higher Order Component, lets see an updated example using Higher Order Components.

```js
// Higher Order Component that Contians the logic
// to detect the hover.
function withHover(WrappedComponent) {
  return function (props) {
    const [isHovered, setHovered] = useState(false);

    function handleMouseEnter() {
      setHovered(true);
    }

    function handleMouseLeave() {
      setHovered(false);
    }

    return (
      <div onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
        <WrappedComponent {...props} isHovered={isHovered} />
      </div>
    );
  };
}

// Updated Text Component without the Hover Logic
const TextComponent = ({ text, isHovered }) => {
  return (
    <>
      <p style={{ backgroundColor: isHovered ? "blue" : "white" }}>{text}</p>
    </>
  );
};

// Updated Input Component without the Hover Logic
const InputComponent = ({ type, isHovered }) => {
  return (
    <input
      type={type}
      style={{ backgroundColor: isHovered ? "blue" : "white" }}
    />
  );
};

// Creating components that contain hover logic using
// Higher Order Component.
const TextComponentWithHover = withHover(TextComponent);
const InputComponentWithHover = withHover(InputComponent);

// Using the Components in our App
const App = () => {
  return (
    <div className="App">
      <TextComponentWithHover
        text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
        veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
        commodo consequat."
      />

      <InputComponentWithHover type="text" />
    </div>
  );
};

export default App;
```

In the above code example, we have created a Higher Order Component named `withHover`.  

In the `withHover` Higher Order Component, we are handling the `MouseEnter` and `MouseLeave` events and setting the value of `isHovered` to `true` when there is a hover over the componenet.

We are also passing the `isHovered` as a prop to the `WrappedComponent` and we use this prop to handle the hover condition in the `WrappedComponents`.

We have also updated the `TextComponent` and the code of the `TextComponent` has become much smaller. In the `TextComponent` we are just checking if the `isHover` the prop is set to `true` and if it is set to true then we are setting the background color to blue.

***Dead Simple Chat offers powerful*** [***Javascript Chat SDK and APIs***](https://deadsimplechat.com/javascript-chat-api-sdk) ***that you can use to easily add Chat functionality to your React Applications.***

## Common Use Case Patterns for HOCs

Now let's discuss some common use case patterns where using Higher Order Components would be beneficial.

### 1\. Management of State and Handling of Async Data

Higher order components can be used to manage state and perform async data retrieval and normal components would be focused on displaying the data.

This results in the creation of loosely coupled components with a clear separation of roles.  Let's look at an example:

#### Example:

```js
import "./styles.css";
import { useState, useEffect } from "react";

function withDataFetch(WrappedComponent, fetchData) {
  return function (props) {
    const [data, setData] = useState(null);
    const [isLoading, setIsLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
      const fetchWrapper = async () => {
        try {
          const data = await fetchData(props);
          setData(data);
          setIsLoading(false);
        } catch (error) {
          setError(error);
          setIsLoading(false);
        }
      };
      fetchWrapper();
    }, [props]);

    return (
      <WrappedComponent
        {...props}
        data={data}
        isLoading={isLoading}
        error={error}
      />
    );
  };
}

const fetchPosts = async () => {
  const response = await fetch("https://jsonplaceholder.typicode.com/posts");
  const data = await response.json();
  return data;
};

const PostComponent = ({ data, isLoading, error }) => {
  if (isLoading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

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

const PostComponentWithData = withDataFetch(PostComponent, fetchPosts);

export default function App() {
  return (
    <div className="App">
      <PostComponentWithData />
    </div>
  );
}
```

In the above code example, we have created a Higher Order Component called as `withDataFetch`. This HOC accepts a component and a method to fetch the data as an argument.

The HOC contains the logic to call the `fetchData` method to retrieve the data, pass the data to the `WrappedComponent`. It also passes the `isLoading` and `error` state to the `WrappedComponent` so that the componenet can display appropriate UI to the user.

Then we create our `PostComponent`. The `PostComponet` displays the data in a list and also checks for `error` and `isLoading` props and display appropriate messages.

Finally, we create our `fetchPosts` method, which calls the [`jsonplaceholder.typicode.com/posts`](http://jsonplaceholder.typicode.com/posts) API to fetch a list of mock posts.

We are then calling our HOC, and passing our `PostComponent` and our data fetch method `fetchPosts` and generating a wrapped component `PostComponentWithData` and adding it to our app.

And the `PostComponetWithData` displays a list of Posts:

![](https://deadsimplechat.com/blog/content/images/2023/04/image-5.png align="left")

**With Dead Simple Chat you can easily add Chat Functionality to your application. Powerful** [**JavaScript Chat SDK**](https://deadsimplechat.com/javascript-chat-api-sdk) **provided by Dead Simple Chat allows you to add chat in minutes.**

### 2\. Conditional Rendering: Authorization and Feature Toggle

Higher Order Components can also be used to show components only if they meet a condition.

For e.g: A set of components should only be displayed to authorized users or experimental features should be enabled only if the feature flag is set.

So, using Higher Order Components we can abstract away the logic to fetch the info if the componenet should be shown or not and reuse it in multiple components.

#### Example 1: Authorization

Let's look at an example below:

```js
import "./styles.css";

// Higher Order Component
function withAuthorization(WrappedComponent, checkPermissions) {
  return function (props) {
    // You can also wrap it in useEffect for async permission checks.
    return checkPermissions(props) ? (
      <WrappedComponent {...props} />
    ) : (
      <p>Please login with appropriate role</p>
    );
  };
}

const PrivateComponent = () => {
  return <div>This is a Private Component, only visible to Admin Users.</div>;
};

const checkPermission = (props) => {
  return props.userRole === "admin";
};

const PrivateComponentComponentWithAuthorization = withAuthorization(
  PrivateComponent,
  checkPermission
);

export default function App() {
  return (
    <div className="App">
      <PrivateComponentComponentWithAuthorization userRole="admin" />

      <PrivateComponentComponentWithAuthorization userRole="guest" />
    </div>
  );
}
```

In the above code, we have created a Higher Order Component called as `withAuthorization`.

The HOC accepts a `WrappedComponent` and the method called as `checkPermissions` to check if the user has permission to view the `WrappedComponenet`

Right now in our example, we are assuming the `checkPermission` method is synchronous, but this example can also be easily modified to be used with async permission checking by using the `useEffect` hook.

To learn how to use the `useEffect` hook in the HOCs see the previous fetchPosts example.

Next, we created a componenet called the `PrivateComponent`. The `PrivateComponent` has no logic for checking the user permission, this component should only be displayed to admin users.

Then finally we create a very basic method to check the permission called the `checkPermission` method. This method just checks if the `userRole` is `admin`.

##### Example 2: Feature Toggle

Here is an example to add a feature toggle using Higher-order components:

```js
import "./styles.css";
import React from "react";

function withFeatureToggle(WrappedComponent, featureEnabled) {
  return function (props) {
    return featureEnabled ? <WrappedComponent {...props} /> : <></>;
  };
}

const NewFeatureComponent = () => {
  return (
    <div>
      <button>New Feature</button>
    </div>
  );
};

// Global Feature Toggle.
const enableNewFeatures = false;

const NewFeatureComponentWithFeatureToggle = withFeatureToggle(
  NewFeatureComponent,
  enableNewFeatures
);

export default function App() {
  return (
    <div className="App">
      <NewFeatureComponentWithFeatureToggle />
    </div>
  );
}
```

We have created a global feature toggle called as `enableNewFeatures` when it set to true the component `NewFeatureComponent` will be displayed otherwise it will be hidden.

***Dead Simple Chat offers powerful*** [***Javascript Chat SDK and APIs***](https://deadsimplechat.com/javascript-chat-api-sdk) ***that you can use to easily add Chat functionality to your React Applications.***

### 3\. Translation and Language Switching

Higher-order components can also be used to add Translation, internationalization and the ability to easily switch between languages.

Let's look at an example:

```js
import "./styles.css";

import React, { useState } from 'react';

const i18n = {
  en: {
    "Please Login": 'Please Login',
  },
  es: {
    "Please Login": 'Por favor Iniciar sesión',
  },
  fr: {
    "Please Login": 'Veuillez vous connecter'
  }
};

function withTranslation(WrappedComponent, translation) {
  return function (props) {
    const [language, setLanguage] = useState('en');

    const translate = (key) => translation[language][key] || key;

    const changeLanguage = (lang) => {
      setLanguage(lang);
    };

    return (
      <WrappedComponent
        {...props}
        t={translate}
        language={language}
        changeLanguage={changeLanguage}
      />
    );
  };
}


const LoginComponent = ({ t, language, changeLanguage }) => {
  return (
    <div>
      <p>{t('Please Login')}</p>
      <p>Current language: {language}</p>
      <button onClick={() => changeLanguage('en')}>English</button>
      <button onClick={() => changeLanguage('es')}>Español</button>
      <button onClick={() => changeLanguage('fr')}>Français</button>

    </div>
  );
};

const LoginComponentWithTranslation = withTranslation(LoginComponent, i18n);


export default function App() {
  return (
    <div className="App">
    <LoginComponentWithTranslation />
    </div>
  );
}
```

Let's understand the above example. We have created an object called as `i18n` that contain the translations for 3 languages.

Then we are creating a higher-order component called as `withTranslation` that accepts a component and transitions as an argument.

The `withTranslation` HOC returns a sub-object of the `i18n` object based on the language selected by the user. It also offers a method to change the selected language.

We are then creating our `LoginComponent`, the `LoginComponent` accepts the props from the Higher Order Component, which include the translations stored in the prop `t` , currently selected language in the prop `language` and `changeLanguage` method.

Finally, we are creating a component called `LoginComponentWithTranslation` using our HOC that allows us to easily switch between languages.

***Dead Simple Chat offers powerful*** [***Javascript Chat SDK and APIs***](https://deadsimplechat.com/javascript-chat-api-sdk) ***that you can use to easily add Chat functionality to your React Applications.***

### 4\. Error Boundary

Higher Order Components can also be used to handle un-handeled errors using Error Boundaries. Once caveat is that the Error Boundary is not supported in functional components.

Hence, only the HOC has to be the class componenet, the `WrappedComponent` can be a functional component.

Let's check out an example of Error Boundary using and HOC:

```js
import React, { Component } from "react";

function withErrorBoundary(WrappedComponent) {
  return class ErrorBoundary extends Component {
    constructor(props) {
      super(props);
      this.state = { hasError: false, error: null };
    }

    static getDerivedStateFromError(error) {
      return { hasError: true, error };
    }

    componentDidCatch(error, errorInfo) {
      console.error("Error handled by ErrorBoundary:", error, errorInfo);
    }

    render() {
      if (this.state.hasError) {
        return <p>Something went wrong: {this.state.error.message}</p>;
      }

      return <WrappedComponent {...this.props} />;
    }
  };
}

const DataViewerComponent = ({ data }) => {
  if (!data) {
    throw new Error("Please specify the data");
  }

  return (
    <div>
      <h2>Data:</h2>
      {data}
    </div>
  );
};

const DataViewerWithErrorBoundary = withErrorBoundary(DataViewerComponent);

export default function App() {
  return (
    <div className="App">
      <DataViewerWithErrorBoundary />
    </div>
  );
}
```

In the above code we have created a HOC `withErrorBoundary` that returns a class component that wraps and Error Boundary around the `WrappedComponent`.

Whenever an exception occurs the `getDerivedStateFromError` is called, and we are store the error in the state and setting the `hasError` to `true`.

When `hasError` is set to true we are displaying the message "Something went wrong:" and the Error Message.

If `hasError` is set to false then we are displaying the `<WrappedComponent />`

Then we are creating a `DataViewerComponent` and throwing an error in the `DataViewerComponent` if the `data` prop is empty.

![](https://deadsimplechat.com/blog/content/images/2023/04/Screenshot-2023-04-17-at-2.57.00-PM.png align="left")

When we will run the app you can see the message "Something went wrong: Please specify the data" message displayed.

[Javascript Chat API and SDK | DeadSimpleChat](https://deadsimplechat.com/javascript-chat-api-sdk)

[Easily add chat to your website or app within seconds. Pre-built chat with API and Javascript SDK | DeadSimpleChat.](https://deadsimplechat.com/javascript-chat-api-sdk)

![](https://cdn.deadsimplechat.com/production/2.19.10/public/favicon.ico align="left")

[DeadSimpleChat](https://deadsimplechat.com/javascript-chat-api-sdk)

![](https://cdn.deadsimplechat.com/production/2.19.10/public/images/javascript-chat-api-sdk.svg align="left")

## Naming Conventions

We have seen many examples with Higher Order Components in this blog post. You might have noticed the HOCs being with the word `with`.

`withErrorBoundary`, `withTranslation` etc. There are no strict naming conventions with Higher Order Components but it is a good practice to prefix the HOC with the keyword `with`.

And the new component that we create after wrapping them with the HOC should contain the name of the HOC to indicate that this component has been enhanced with and HOC.

For e.g: We had created a HOC `withTranslation` and a component called as the `LoginComponent` and our enhanced componenet was called `LoginComponentWithTranslation`

```js
const LoginComponentWithTranslation = withTranslation(LoginComponent, i18n);
```

## Conclusion

In this blog post, we have learned what are Higher Order Components, how to create simple Higher Order Components.

We have also seen examples of scenarios where Higher Order Components are commonly used.

Hopefully, this post will give you a good understanding of how and where to use Higher Order Components in your application.

HOC is a good React pattern that promotes code reuse and helps you create clean and maintainable code.

This blog post was originally written on : [Higher Order Components in React: Examples with Common Use-case Patterns](https://deadsimplechat.com/blog/higher-order-componets-in-react/)