What Are Higher-order Components in React?

Read it in 8 Mins

Last updated on
07th Jun, 2022
Published
14th Dec, 2021
Views
7,491
What Are Higher-order Components in React?

In react, a higher-order component (HOC) is deemed an advanced technique for reusing component logic. They are not part of the React API, but they are the model that begins from React’s compositional nature. 

A higher-order function takes a function as an argument and returns a function. HOC is not a feature in React or any other programming language. It is a pattern that emerged from the components nature of React. Examples of the higher-order functions are the; .map, .filter, etc. Click here to know more about usereducer hook in React. 

How to Define a Higher Order Function

Example 1: Function that takes another function as an argument 

object FunctionThatTakesFunction extends App {  
  def math(a:Int, b:Int, fun:(Int,Int)=>Int):Int = fun(a,b)  
  val sum = math(5, 6, (a,b) => a+b)  
  val diff = math(10, 4, (a,b) => a-b)  
  println(s"sum is $sum")  
  println(s"diff is $diff")  
 

Output:  

sum is 11  
diff is 6  

Example 2: Function that sums an array of numbers: 

function calculate(numbers) { 
  let sum = 0;  
 for (const number of numbers) {  
 sum = sum + number;  
  }  
return sum;  
 
calculate([1, 2, 4]); // => 7  

Output  

Sum = 7  

Anonymous Functions  

Before starting with higher-order functions, let us discuss anonymous functions. Anonymous functions are used in JavaScript to make the code easier to read. An anonymous function can be assigned to a variable or passed into other functions, like higher-order functions.  

Anonymous functions, sometimes referred to as lambdas are often used when declaring higher-order functions or in cases where the function is only used once. The latter case is important when considering performance because it saves time and memory since anonymous functions do not need to be stored for later use.  

For example, A simple anonymous function is like:  

x -> x + 1  

Here, the input of the function is x, and the output is x + 1.  

The syntax for anonymous functions is slightly different in all languages, but it is usually written as (input) → (output).  

Anonymous functions are often used because they avoid the boilerplate code associated with named function declarations. Therefore, for simple functions that do not need to be re-used across multiple places, such as the one above, an anonymous function may be more appropriate.

Common Higher-Order Functions

There are a few higher-order functions that are essential to modern codebases. These provide a way to iterate or summarize lists of data. They make code much cleaner by dealing with common list operations instead of having to create a lot of helper code for basic list operations. The clarity in intent from using them is immensely helpful as well. 

Filter  

The Filter is a function that accepts as an argument a test function that should return a boolean value and returns a new array with only those elements for which the test function returned true.   

Map  

The map is a function that turns one component into another component by adding a function to each element. It is a user's work to describe how to replace each element.  

Reduce  

The reduce function is a slightly different task than the previous one. It takes all the components in a group and adds them using binary values/operations to produce a single value. 

What are Higher Order Components?

A higher-order component (HOC) is a distinctive element for reusing logic in React components. Members use one or more elements as arguments and return a new enhanced feature. Sounds familiar, right? They are similar to higher-order functions, which take some functions as an argument and produce a new function. 

HOCs are commonly used to compose components with shared behaviour. It combines differently from regular state-to-props patterns. 

Higher-Order Components(HOCS Facts)

  1. It doesn't modify or mutate components but creates new ones. 
  2. They are used to compose pieces and can be reused. 
  3. A pure function with no side effects and returns only a new feature. 

Examples of real-world HOCs:

react-reduxConnect(mapStateToProps, mapDispatchToProps) (UserPage)
react-routerwithRouter(UserPage)
material-uiwithStyles(styles)(UserPage)

Higher-Order Component Structure

The below snippet shows HOC structure in React: 

import React from 'react'; 
// Take in a component as argument InsideWrappedComponent
const higherOrderwrappedComponent = (InsideWrappedComponent) => { 
// And return another component 
  class HOC extends React.Component { 
    render() { 
      return <InsideWrappedComponent/>; 
    } 
  } 
  return HOC; 
}; 

The higher-order component uses a component (InsideWrappedComponent) and returns another part inside it. As a result of this component’s logic, it can create a HOC out of that component and can be used and scaled wherever necessary. 

Some Points to Remember

Before using HOC, there are certain things that an individual should always keep in mind. These include the following:   

Components should be pure

Side effects of the HOC should be avoided. HOC should compose a component for reuse. Avoid the temptation to nutate the component passed as an argument. If the component is mutated the new behaviour would also be reflected outside the enhanced component and hence the component becomes non-reusable. Use composition instead of mutation. 

HOC convention naming

Choosing a display name will help to debug/read the code properly. For example, if HOC is withLoadingIndicator and the input component is Component then the return component can have a display name as withLoadingIndicator(Component).

Invoking HOC inside the render method should be avoided

Invoking the HOC inside the render refers to every time that the HOC component is rendered/ invoked. This results in performance degradation. It is better to invoke HOD from the outside component. 

Example

render(){  
  const RenderedComponentDegrade = HOC(Component);  
  return <RenderedComponentDegrade/>;  
};   

Creating the HOC inside the render leads to the creation of a new component. This leads to unmounting and remounting of the component, making the descendants lose their state.   

Copying static methods

It is important to declare static methods in the class. Binding the component where the static method is defined the component would not have access to a static method   

Passing refs

Passing props is not possible with refs as refs are not handled by React like ordinary props. We should use forwardRef API to handle this as a solution. 

Advantages of Using Higher-Order Components

  • High order components when used properly and efficiently are easy to handle  
  • High order components help to get rid of mutating or comoving the same logic in each component created  
  • Using High order components makes code more readable and efficient. Due to its proper naming conventions debugging of code becomes easy. 

Building Higher-Order Components - By Examples (2 - 3 examples)

Higher-Order Component (HOC) refers to wrapping around "normal" components. It is a function that takes as input of one component and returns another component that wraps the original component.  

A simple example below would help us to easily understand how this concept works.   

Example One:

Step 1: Create the React.js project. 

npm install -g create-react-app 
create-react-app my-app-react 
cd my-app-react 
npm start 

Step 2: Create a file inside the src folder called HOC.js. 

// HOC.js 
import React, {Component} from 'react'; 
export default function HocExample(HocComponentExample){ 
    return class extends Component{ 
        render(){ 
            return ( 
                <div> 
                    <HocComponentExample></HocComponentExample> 
                </div> 
 
            ); 
        } 
    }  
} 
 
Include function HocExample in the file App.js file 
// App.js 
import React, { Component } from 'react'; 
import HocExample from './HOC'; 
class AppExample extends Component { 
    render() { 
    return ( 
      <div> 
        Higher-Order Component First Example  
      </div> 
    ) 
  } 
} 
AppExample = HocExample(AppExample); 
export default AppExample; 

Explanation 

  • First, we have created a function that is HocExample inside the HOC.js file. 
  • HocExample function accepts one argument as a component.  
  • Component is AppExample 
  • AppExample = HocExample(AppExample ); 
  • The component is wrapped inside another React component. It is easily scalable and can be modified. It is the primary application of the Higher-Order Components. 

Example Two: 

import React from 'react';  
 var newDataHOC = {  
   data: 'Example for high order component.',  
 
 
 var MyHOCExample = ComposedComponent => class extends React.Component {  
   componentDidMount() {  
      this.setState({  
         data: newDataHOC.data  
      });  
   }  
   render() {  
      return <ComposedComponent {...this.props} {...this.state} />;  
   }  
};  
class MyComponent extends React.Component {  
   render() {  
      return (  
         <div>  
            < h1 >{this.props.data}</h1>  
         </div>  
      )  
   }  
}   
export default MyHOCExample(MyComponent);  

Note − Data is Passed to MyComponent. The MyHOCExample is a higher-order function that passes data to MyComponent. This function takes MyComponent, enhances with newDataHOC, and returns the enhanced component that is rendered on the screen.   

Using HOC would help our app to maintain easily, efficiently and also help to upgrade.  

Example Three: 

  • Checking authentication using HOC 
  • A component that would be displayed if the user is logged in. Create a HOC component that checks the authentication on each render(): 
  • AuthenticatedUserComponent.js 
import React from "react"; 
export function requireAuthenticationExample(Component) { 
    return class AuthenticatedExampleComponent extends React.Component { 
        isAuthenticated() { 
            return this.props.isAuthenticated; 
        } 
 
        /** 
         * Render 
         */ 
        render() { 
            const loginErrorMessage = ( 
                <div> 
                    Please <a href="/login">login</a> To view this part of the application. 
                </div> 
            ); 
 
            return ( 
                <div> 
                    { this.isAuthenticated === true ? <Component {...this.props} /> : loginErrorMessage } 
                </div> 
            ); 
        } 
    }; 
} 

export default requireAuthenticationExample; 

Use Higher Order Component in our components that would be hidden from anonymous users: 

 

import React from "react"; 
import {requireAuthenticationExample} from "./AuthenticatedExampleComponent"; 
export class MyPrivateComponentExample extends React.Component { 
    /** 
     * Render 
     */ 
    render() { 
        return ( 
            <div> 
                Viewable only to anonymous users. This is a secret search and hidden from other users. 
            </div> 
        ); 
    } 
} 

export default requireAuthenticationExample(MyPrivateComponentExample); 

Debugging HOCs

HOCs debugging including printf statement Editing the source code of the application to log the application state at the appropriate points, either through print statements or a logging framework.  

Compiling and running the application viewing debugging statements emitted by the application at runtime   

Debugging with print statements is crude, but fast and easy. One downside is that adding a print statement inherently changes the flow of the program, which may or may not be important. Additionally, an individual print statement inherently gives no indication of where in the code it was emitted. With a small number of debugging print statements, this may not be a problem. With a large number of print statements, they can be difficult to sort out and understand.  

logging framework provides several advantages over print statements. Logging frameworks usually provide some sort of log routine, which is used to emit a message with the corresponding priority. The framework itself directs the output to some destination, along with useful information such as timestamps, the name of the class or source file that contains the log statement, and even line code line numbers.   

Similarly, the logging framework can filter logged messages based on priority or logging level or disable logging at all. For this reason, in contrast to the transient nature of printf statements, logging statements are usually kept indefinitely in the codebase, making it a deployment-time decision whether to log them to a file.  

Summing up 

Higher-order functions in JS are special functions that accept functions as arguments or return them. Furthermore, if only primitives are used by functions/components as arguments or return values, then these are first-order functions. HOC offers reusability benefits: Higher-order functions provide the core behavior itself, and with the acceptance of function as an argument you can extend that behavior. 

Profile

Rajesh Bhagia

Blog Author

Rajesh Bhagia is experienced campaigner in Lamp technologies and has 10 years of experience in Project Management. He has worked in Multinational companies and has handled small to very complex projects single-handedly. He started his career as Junior Programmer and has evolved in different positions including Project Manager of Projects in E-commerce Portals. Currently, he is handling one of the largest project in E-commerce Domain in MNC company which deals in nearly 9.5 million SKU's.

In his role as Project Manager at MNC company, Rajesh fosters an environment of teamwork and ensures that strategy is clearly defined while overseeing performance and maintaining morale. His strong communication and client service skills enhance his process-driven management philosophy.

Rajesh is a certified Zend Professional and has developed a flair for implementing PMP Knowledge Areas in daily work schedules. He has well understood the importance of these process and considers that using the knowledge Areas efficiently and correctly can turn projects to success. He also writes articles/blogs on Technology and Management