5 Essential React Concepts to Know Before Learning Redux

Higher Order Components in React

Implementing higher order components has proven to be a great pattern when building React applications. Asides from injecting additional functionality into existing components, higher order components are useful in implementing separation of concerns in components in a functional way. In this post, we will walk through what higher order components are, what they are used for and how to implement them.Since this is an extensive topic, feel free to comment if I missed out on something. In this post, it is assumed that the reader is at an advanced level in React and also well versed in ES6 methods. Great places to check out when getting started with React include the React Docs as well as this comprehensive video course on React by Alex Sears. Let’s get started!

What are Higher Order Components?

Higher Order Components are simply React components that are wrapped around other component. This pattern can be said to be similar to higher order functions; a higher order function is a function that when called, returns another function. Higher Order Components are usually implemented as methods which returns you a customized class and not an instantiated one. Below is an example of how higher order components are described in the programing language Haskell:

  hocFactory:: W: React.Component => E: React.Component

Where W (WrappedComponent) is the React component being wrapped and E (Enhanced Component) is the new, React component (a higher order component of course) being returned. So what does it mean to “wrap” around a component? We will get to that in a bit.

Creating a Higher Order Component

Creating a higher order component basically involves manipulating WrappedComponent which can be done in two ways:

  • Props Proxy
  • Inheritance Inversion

Props Proxy can be implemented thus:

  function ppHOC(WrappedComponent) {
    return class PP extends React.Component {
      render() {
        return <WrappedComponent {...this.props}/>
      }
    }
  }

Notice how the render method of the higher order component returns a React Element which is exactly the type of the WrappedComponent. Asides that, the props received by the higher order component is also passed through hence the name Props Proxy. Props Proxy can be implemented via a number of ways which include but are not limited to:

  • Manipulating props
  • Abstracting State
  • Accessing the instance via Refs

Inheritance Inversion is a bit different. It allows higher order components to access the WrappedComponent instance via the this keyword, this implies that it can access props, state and render methods. Here’s how Inheritance Inversion is implemented:

  function iiHOC(WrappedComponent) {
    return class Enhancer extends WrappedComponent {
      render() {
        return super.render()
      }
    }
  }

Notice how the returned higher order component class (Enhancer) extends WrappedComponent and not the other way round (WrappedComponent extending the Enhancer class)? The bond between both seems reversed thus the name Inheritance Inversion. Inheritance Inversion can be used in:

  • Conditional Rendering
  • State Manipulation

Implementing a Higher Order Component

You’ve probably implemented a higher order component in your application if you’ve used React-Redux. Its primary function connect, is a higher order function. connect accepts a component and returns a component connected to the Redux store, wrapping the one provided, saving you the trouble of managing the logic connection to the store in multiple places in your application.

When building an application, you’ll likely have subcomponents that have different behaviors. A common practice is to pass this behavior through props. Suppose you’ve got a component like this:

  import React from 'react'

  class HeadComponent extends React.Component {
    render() {
      return (
        <div onClick={this.props.onClick}
            style={this.props.style}>

          <h1>{ this.props.title }</h1>
          <p>{ this.props.text }</p>
        </div>
      );
    }
  }

Using JSX, we could pass an onClick event to HeadComponent above:

  import React from 'react'

  class ClickCount extends React.Component {
    constructor(props) {
      super(props);

      this.onClick = this.onClick.bind(this);
    }

    onClick(e) {
      console.log(e)
    }

    render() {
      return (
        <div>
          <HeadComponent {...this.props} onClick={this.onClick} />
        </div>
      );
    }
  }

So far it has all been basic React. Suppose we wanted onClick to carry out certain extensive operations such as accessing state or passing it through props to multiple components. We could create an instance of ClickCount for every time we need to wrap a component where we’ll pass our click handler. However that would be repetitive and could easily lead to spaghetti code, now this is where higher order components come in. Check out this block of code that shows how we can pass our event handler into multiple components without being repetitive:

  import React from 'react'

  const ClickWrapper = (WrappedComponent) => {
    return class ClickCount extends React.Component {
      constructor(props) {
        super(props);

        this.onClick = this.onClick.bind(this);
      }

      onClick(e) {
        console.log(e)
      }

      render() {
        const { title, content } = this.props;
        return (
          <div>
            <WrappedComponent {...this.props} onClick={this.onClick} />
          </div>
        );
      }
    }
  }

Using the spread operator we passed all props from ClickWrapper to the wrapped component, this allows the higher order component to be used in place of the wrapped component. With this, we can create a component that calls the click handler any time it is clicked using the following:

  const ReplaceComponent = ClickWrapper(HeadComponent);

Another implementation of higher order components is in state abstraction. We can abstract state by providing props and callbacks to WrappedComponent. In the following example, using the Props Proxy(PP) method of manipulating state, we will extract the value and onChange handler of the age input field:

  function ppHOC(WrappedComponent) {
    return class PP extends React.Component {
      constructor(props) {
        super(props)
        this.state = {
          age: ''
        }
        this.onNameChange = this.onNameChange.bind(this)
      }
      onNameChange(event) {
        this.setState({
          age: event.target.value
        })
      }
      render() {
        const changeProp = {
          age: {
            value: this.state.age,
            onChange: this.onNameChange
          }
        }
        return <WrappedComponent {...this.props} {...changeProp}/>
      }
    }
  }

We would implement it in this fashion:

  @ppHOC
  class hocExample extends React.Component {
    render() {
      return <input age="age" {...this.props.age}/>
    }
  }

Let’s take a look at how we can use Inheritance Inversion to implement conditional rendering. In the example below, assuming the higher order component will render receives the dailyLimit prop, it would render exactly what WrappedComponent would render given that this.props.dailyLimit is true:

  function iiHOC(WrappedComponent) {
    return class Enhancer extends WrappedComponent {
      render() {
        if (this.props.dailyLimit) {
          return super.render()
        } else {
          return null
        }
      }
    }
  }

Summary

At the most basic level, higher order components are functions that return a class and are the implementations of functional programming principles in your codebase so as to make it cleaner and easier to work with and maintain. It’s also possible to pass higher order components into other higher order components since typically they take components as input and return other components as output. Libraries such as React-Redux and React-Router are great examples of why we should think about implementing higher order components more often from now on.