Simple explanation of Higher-Order Components (HOC)

I got an email from a reader.

Could you please write a simple article on HOC(higher order component). Facing difficulty while learning it.

Higher-order components are a bit tricky to wrap one’s head around. So in this article we will take it from the beginning and we will keep it simple.

The concept higher-order component comes from the functional programming concept higher-order function. Let’s start by looking into what higher-order functions are.

Higher-Order Functions

Higher-order function is a general concept that applies to many programming languages, including JavaScript.

Higher-order functions are regular functions that do one or both of the following:

  1. Takes one or many functions as arguments
  2. Returns a function

Let’s look at simple examples of these two.

1. Takes one or many functions as arguments

An example of a function that takes another function as argument is this:

function twice(f, v) {
  return f(f(v));
}

It takes a function called f, and calls it twice. This is an example usage:

function add3(v) {
  return v + 3;
}
const result = twice(add3, 1);
console.log("Result is ", result);

That output would be:

Result is 7

 

2. Returns a function

An example of a function that returns another function is this:

function addX(x) {
  return function (y) {
    return x + y;
  }
}

And we would use it like this:

const add1 = addX(1);
add1(5); // will return 6

We could also call the returned function directly without assigning it to a variable:

addX(1)(5); // will return 6

Tricky?

If you are not 100% confident about how higher-order functions work, I want to advise you to open up a JavaScript REPL and play around with it. I put the code in an online REPL here.

It is easier to understand higher-order components when you have a feeling for higher-order functions.

Higher-order components

Ok, now we know what higher-order functions are. Higher-order components (HOC) are a very similar concept. Instead of working with functions as input parameters and return values, HOCs are working with components.

The most simple HOC

A HOC takes a component as input parameter and returns a new component. Let’s look at an example of the most simple HOC possible.

// Take in a component as argument WrappedComponent
function simpleHOC(WrappedComponent) {
  // And return a new anonymous component
  return class extends React.Component{
    render() {
      return <WrappedComponent {...this.props}/>;
    }
  }
}

This HOC takes a React component, WrappedComponent, as parameter. It returns a new React component. The returned component contains the WrappedComponent as a child.

We use the HOC to create a new component like this:

// Create a new component
const NewComponent = simpleHOC(Hello);

// NewComponent can be used exactly like any component
// In this case, NewComponent is functionally the same as Hello
<NewComponent/>

Click here to see a fully working example.

Use HOC to enhance components

The HOC we just created does not do anything to the component, it just returns the same component with a wrapper component around it. It’s not much point with that, is it?

The idea with HOC is to enhance components with functions or data.

Let’s look at an example of an HOC that enhances the component.

The way we are going to do that is to add a prop to the component. Let’s add a name prop with the value “React”. It would look something like this:

// Take in a component as argument WrappedComponent
function withNameReact(WrappedComponent) {
  // And return a new anonymous component
  return class extends React.Component{
    render(){
      return <WrappedComponent
                name="React"
                {...this.props} />;
    }
  }
}

Lets take a look how we can use it.

First, we define the component to send in, which uses the name prop…

const Hello = ({ name }) => <h1>Hello {name}!</h1>;

…then we will enhance it with our HOC.

const HelloReact = withNameReact(Hello);

// No need to send in the name prop, it is already sent in 
// by the HOC. It will output Hello React!
<HelloReact/> 

Click here to see a fully working example

Observations

HOC is a powerful concept that is used to enhance a component with new functions or data. It is worth noting the following:

  • We don’t modify or mutate the component. We create new ones.
  • A HOC is used to compose components for code reuse.
  • A HOC is a pure function. That means it has no side effects. It only returns a new component.

Summary and next steps

You have learned the basic principles behind HOC.

Now you can dive deeper into the subject and learn what problems HOC solves and when to use them. A good start is the section about HOC in the official React docs.

Master the React ecosystem!

Get an email everytime I post by signing up to the email list.

Subscribe now and you will get a free code review checklist you can use to improve your own code

  • Subramanya Chakravarthy

    Great explanation, thank you very much

    • jakoblind

      You’re welcome! Glad it was useful! 🙂

  • Michael Herold

    I feel like this article is missing the third piece of the argument, which is why you’d implement a generic withNameReact HOC to get to HelloReact instead of writing HelloReact first and passing in the name prop directly to Hello.

    I suppose it’s the “reuse” step that is being handwaved over, but it’s the primary reason to write an HOC. And I feel like they’re often arrived at when refactoring redundant code, which might make for a better example.

    Great article though!

    • jakoblind

      I agree I didn’t focus much on the motivation behind HOC. In this article I wanted to focus on the “how” and not so much on the “why”.

      Happy you liked it!