React Higher-Order Components

A higher-order component (HOC) is an advanced technique in React for reusing component logic.

Simply, a higher order component is a function that takes a component and return a new component.

To understand this better, we will take authentication example. Our use case is that users are allowed to visit products page only if they are authenticated.

Let's assume that after user is authenticated, we save the token in the local storage.

localStorage.setItem("accessToken", token);

Now, let's write the HOC called requireAuth

import React, { ComponentType, FC } from 'react';
import { Redirect } from 'react-router-dom';

const requireAuth = <P extends any>(Component: ComponentType<P>,): FC<P> => (props) => {

	// get token from the local storage
    const isAuthenticated = localStorage.getItem("accessToken") as string;
    
    // user is authenticated, render the component
    if (isAuthenticated) {
      return <Component {...props} />;
    }
    
    // user is not authenticated, redirect to login page
    return (
      <Redirect
        to={{
          pathname: '/auth/login',
        }}
      />
    );
  };

export default requireAuth;

In the example above, I get the token from local storage and then, conditionally render the component or redirect to the /auth/login page.

To use HOC, we can simply decorate as below

 <div>
   <Switch>
          <Route path="/" exact component={Home} />
          <Route path="/products" exact component={Products} />
          
          // using HOC to check whether the user is authenticated
          <Route path="/services" exact component={requireAuth(Services)} />
          
          <Route path="/auth/login" exact component={Login} />
    </Switch>
  </div>

Later, if we need to apply the same logic to Products page, we can simply re-use the logic as below

 <div>
   <Switch>
          <Route path="/" exact component={Home} />
          
          // reusing the logic to this page
          <Route path="/products" exact component={requireAuth(Products)} />
          
          // using HOC to check whether the user is authenticated
          <Route path="/services" exact component={requireAuth(Services)} />
          
          <Route path="/auth/login" exact component={Login} />
    </Switch>
  </div>