DEV Community

vinodchauhan7
vinodchauhan7

Posted on

High Order Component (HOC) in React. What & Why?

Till the date whether you are an experienced developer or a beginner, you must know the paramount rule of programming i.e D.R.A (Don't Repeat Yourself) which means you must avoid duplicate code. Considering this ReactJs developers used the term HOC (High Order Components) to reduce the efforts of redundant code. However this term is directly and indirectly related to High Order Function of Javascript.

NOTE : HOC or HOF are just design patterns.These are terms used to define a way to reduce the efforts and needs of common code.

In order to understand the whole concept, lets first just understand what is High-order-functions? As we all know that functions are objects in javascript, that means functions can be assigned to a variable or passed to a other function as argument like other objects, Right? If that is true it means we can also return function as a result of another function, Am I right?

Above statement is very much true, And this information makes javascript a very special language. We can do functional programming in this way. Classic examples of High Order function are : closures, map,filter,reduce & so on.. Dont' worry if you have never used or heard about this HOF.

var company = function(employeeName,companyName){
    console.log(employeeName+" is working in "+companyName);
}

var employee1 = function(employeeName,companyReference){
    return companyReference(employeeName,"Altran");
}

var employee2 = function(employeeName,companyReference){
    return companyReference(employeeName,"Altran");
}

employee1("Vinod",company);

employee2("Nikhil",company);

output : 
1) Vinod is working in Altran.
2) Nikhil is working in Altran.

The executable code above is a simple example of high-order function. Here, 'company' is a callback function which is passed in 'employee' function as an argument and returned as a result of 'employee' function. 'employee' is High Order function because it is fulfilling all the requirements to be a HOF.
For example, The map function takes a function as an argument.

[1,2,3,4,5].map((i) => (i*2));
output : (5) [2, 4, 6, 8, 10]

However, lets' suppose if Employee 'Nikhil' has changed his organisation then this strategy of returning function is failed for us. But wait, JS has the solution for us because we can pass another function from a returning function which means nested functions. Lets see example of this scenario.

var company = function(employeeName,companyName){
    console.log(employeeName+" is working in "+companyName);
}

var employeeDetails = function(employeeName, companyRef){
    return function(companyName) {
        return companyRef(employeeName,companyName);
    }
}

var employee1 = employeeDetails("vinod",company);

var employee2 = employeeDetails("nikhil",company);

employee1("Altran"); //Vinod is working in Altran.

employee2("Sapient"); //Nikhil is working in Sapient.

There can be more interesting examples if we use this pattern with composition.
I hope till now we all got understanding of what high order functions are, so now lets jump on High order Components.

High Order Component

If you search for HOC, the definition says that HOC is a component, can take other component as an argument and return a new component. And most importantly the component it returns can render the original component that was passed in. It means HOC have same properties like HOF.

Lets' build an example to understand HOC. Suppose we have three components 'First','Second','Third'. These all components have single button which on click can add a new css class.

App.js


function App() {
  return (
    <div className="App">
      <First />
      <Second></Second>
      <Third></Third>
    </div>
  );
}


//First.js
const First = () => {
  var [buttonPrimary, setButtonClass] = React.useState(false);

  const handleClick = event => {
    buttonPrimary = buttonPrimary ? false : true;
    setButtonClass(buttonPrimary);
  };

  return (
    <div>
      <button
        className={`btn ${buttonPrimary ? "btn-primary" : ""}`}
        onClick={handleClick}
      >
        First
      </button>
    </div>
  );
};


//Second
const Second = () => {
  var [buttonPrimary, setButtonClass] = React.useState(false);

  const handleClick = event => {
    buttonPrimary = buttonPrimary ? false : true;
    setButtonClass(buttonPrimary);
  };

  return (
    <div>
      <button
        className={`btn ${buttonPrimary ? "btn-primary" : ""}`}
        onClick={handleClick}
      >
        Second
      </button>
    </div>
  );
};


//Third.js
const Third = () => {
  var [buttonPrimary, setButtonClass] = React.useState(false);

  const handleClick = event => {
    buttonPrimary = buttonPrimary ? false : true;
    setButtonClass(buttonPrimary);
  };

  return (
    <div>
      <button
        className={`btn ${buttonPrimary ? "btn-primary" : ""}`}
        onClick={handleClick}
      >
        Third
      </button>
    </div>
  );
};


In above example, If you can observe we have a common code for click functionality in each of the components which is against the rule of D.R.Y. On the click of button we are simply adding 'btn-primary' class in button by checking the value of 'buttonPrimary' variable. In this scenario, we can make our 'withClick' High Order Component to reduce the code for this 3 components.

withClick.js

function withClick(Component) {
  return () => {
    var [buttonPrimary, setButtonClass] = React.useState(false);

    const handleClick = () => {
      buttonPrimary = buttonPrimary ? false : true;
      setButtonClass(buttonPrimary);
    };

    return (
      <div onClick={handleClick}>
        <Component buttonPrimary={buttonPrimary}></Component>
      </div>
    );
  };
}

export default withClick;


//First.js
import withClick from "./withClick";

const First = ({ buttonPrimary }) => {
  return (
    <div>
      <button className={`btn ${buttonPrimary ? "btn-primary" : ""}`}>
        First
      </button>
    </div>
  );
};

export default withClick(First);

//Second.js
import withClick from "./withClick";

const Second = ({ buttonPrimary }) => {
  return (
    <div>
      <button className={`btn ${buttonPrimary ? "btn-primary" : ""}`}>
        Second
      </button>
    </div>
  );
};

export default withClick(Second);


//Third.js
import withClick from "./withClick";

const Third = ({ buttonPrimary }) => {
  return (
    <div>
      <button className={`btn ${buttonPrimary ? "btn-primary" : ""}`}>
        Third
      </button>
    </div>
  );
};

export default withClick(Third);

Key point is that we are exporting our all three components by wrapping it in 'withClick' HOC so that these components can get click functionality in them.

In React Docs, it is written and I also like *** is a component transforms props into UI, a higher-order component transforms a component into another component. ***
Hope you understand something from this article and feel free for any clarification.

Top comments (0)