Codementor Events

Introduction to Higher Order Components(HOCs)In React

Published Jun 10, 2019Last updated Dec 06, 2019
Introduction to Higher Order Components(HOCs)In React

The past week got me learning a lot of things, a lot of concepts I would really love to share. I would begin by discussing Higher-order functions(HOCs) In react.

To be able to understand Higher order components in react, we would first need to understand what Higher Order functions are in JavaScript. Higher-order functions in Javascript are functions that take other functions as arguments and return another function. Examples of the higher-order functions are the; .map, .filter, etc. Some of them I wrote about in this article:

It’s important to note that I’m assuming you have prior knowledge of React if you don’t below is an awesome tutorial by traverse media.
That aside let’s jump right in.

Higher Order Components are components that take as argument another component or components and returns a new component. Could be likened to a Higher Order function, well that’s where the name came from. It is an advanced technique in react for re-using the logic of a component. HOC’s could be used when we want to abstract a login component from the other components in a site, and I would demonstrate how. HOCs are commonly used as advanced react patterns for designing some components that share certain behaviors in a way that makes them connected differently than just the normal state-> props pattern. HOCs as an advanced react pattern allows us the capability of reusing component logic. Think about the functionality of the login component I mentioned. The login could be just a form that takes as value a username, and password and performs a check against a database or any storage means if the user exists on the system. if the user does, and the password entered is correct, then the App component would render the content component, but if the user doesn’t exist, the App renders the login component, the same could be applied to when checking if a user on the site still has a valid authentication. This example could be performed using a Higher-order component. But how, the code below demonstrates how.

Say we have an App component as such

import React, { Component } from 'react'

   //below is the app component that would render to the DOM
   export default class App extends Component {
     render() {
       return (
          <div>
            <h1> Hello world </h1>
          </div>
       )
     }
   }

To create a higher order component that would perform the function we want, which is determining which component to render depending on the status of the user's login session, we would first have to create the two components.

Please note, to make this explanation as simple as it could possibly get, I would be creating all of the components inside the app.js file. And also we would be making use of create-react-app, please get it set up

Below, we would be creating both the login and content components, both are actually going to be dummy components simply calling out their names in an h1 tag.

import React, { Component } from 'react'

   // Login Component
   export default function Login {
      return (
         <div>
           <h1>Hi i'm login</h1>
         </div>
      )
   }

   //Content component
   export default function Content {
       return (
          <div>
            <h1>Hi i'm Content</h1>
          </div>
       )
   }

   //App component
   export default class App extends Component {
     render() {
       return (
          <div>
            //Add component to render here
          </div>
       )
     }
   }

Having built out the individual components, it's time for us to create our HOC.

Please note that you can choose to create this in a different file, but to make this article simple and straight to the point, I would be doing everything from a single file.

Copy and paste the following code immediately under the Content component and before the App component.

const withAuthentication = Component1 => Component2 =>
     class extends Component {
       constructor(props) {
         super(props);
         this.state = {
          isLoggedin: false,
         };
       }

       render(){
          if(this.state.isLoggedin) {
            return <Component1 />
          } else {
            return <Component2 />
          }

       }

The above is as simple as a Higher-order Component can be.

It's of vital importance that we note how HOCs are named, it's generally accepted that they are named starting with with and then whatever their specific job is, In our case authentication. That way anyone looking at your code knows it's a Higher-order component without looking at the code, this is especially very important where the HOC leaves in a separate file.

To explain the code. We use what is being referred to as curring in JavaScript to receive the arguments supplied to a HOC. Currying was what we did when we passed the two arguments to the HOC as so; Component1 => Component2 =>, which is actually equivalent to us declaring a method and passing an argument to it, the normal Javascript way.

Further down, the HOC returns an anonymous class which has a state object, that houses the isLoggedin property, which you would manipulate however you want, during the course of developing your application, to determine when a user is logged in and when they are not.

Further down to the render() method, we add a condition to check the state for the value of isLoggedin, so whatever the value is a Component is being returned respectively.

Now, the question in your mind could obviously be how you can get to use this. Pay close attention. Copy and paste the following code immediately under the HOC withAuthentication() we just wrote.

const DoAuthenticate = withAuthentication(Content, Login);

Now by assigning our HOC withAuthenticate to a function DoAuthenticate, we are setting whatever the returned function inside of HOC to DoAuthenticate who from how it's named, shows it's a component.

Because of how our HOC was organized, we need to make sure the Content component stays at the position of Component1 in the HOC because we expect it to be returned when the user is logged and the Login component taking the position of Component2 as defined in the HOC.

Now instead of having to wonder which Component to render to the DOM through the App Component, we just render the DoAuthenticate and allow the HOC do the pondering over for us. In the end, our code should look like so.

import React, { Component } from 'react'

   // Login Component
   export default function Login {
      return (
         <div>
           <h1>Hi i'm login</h1>
         </div>
      )
   }

   //Content component
   export default function Content {
       return (
          <div>
            <h1>Hi i'm Content</h1>
          </div>
       )
   }

   // Higher order Component
   const withAuthentication = Component1 => Component2 =>
     class extends Component {
       constructor(props) {
         super(props);
         this.state = {
          isLoggedin: false,
         };
       }

       render(){
          if(this.state.isLoggedin) {
            return <Component1 />
          } else {
            return <Component2 />
          }

       }

   const DoAuthenticate = withAuthentication(Content, Login);

   //App component
   export default class App extends Component {
     render() {
       return (
          <div>
            <DoAuthenticate />
          </div>
       )
     }
   }

Learning about HOCs was really fun for me and I made two applications during the week, to deepen my understanding of it. Here are links to the applications.

Instaclone a clone of the Instagram application(not a complete clone though...lol) and LambdaTimeX. Would be dropping links to they Repos on the comment section.

To further your knowledge, I would recommend you give this article on HOCs by Sitepen a shot. 🥂🥂🥂🥂

Discover and read more posts from Johnson Ogwuru
get started
post commentsBe the first to share your opinion
Chris Ihler
5 years ago

Did you post links to your repo’s Instaclone and LambdaTimeX? I was hoping to fork them.

Johnson Ogwuru
5 years ago
Show more replies