Higher Order Components in React - Example Tutorial

As a React application grows, it becomes more and more complex. The number of components increases too. With increasing code, you may encounter situations where the same logic is being used in multiple components. Why write the same code everywhere when we can perform code reusability? It is important to understand code reusability and it is recommended to reuse code as much as possible. Higher-Order Components are one such technique. In this article, we will discuss what is Higher-Order Components with the help of a simple example.




Higher-Order Components in React.js

Higher-Order Components are an advanced technique used in React for reusing a component’s logic. Basically, it is a function that takes another component as an argument and returns a new component. So the idea is to take an existing component and reuse its logic to create a new component with additional functionality.

Following is the basic structure of a Higher-Order Component in React.

import React from "react";

 

const HOC = (ExistingComponent) => {

  class HigherOrderComponent extends React.Component {

    render() {

      return <ExistingComponent />;

    }

  }

  return HigherOrderComponent;

};

 



In the above code, “HOC” is the function that takes “ExistingComponent” as an argument. In the function, a new component named “HigherOrderComponent” is created and it renders the “ExistingComponent”. 


In the end, the “HOC” function returns the “HigherOrderComponent”. The “HOC” function is not actually doing anything. It is an example to show how a Higher-Order Component is created.

Let’s understand with the help of a working example. Observe the following component.


import { useState } from "react";

 

const AddCounter = () => {

  const [counter, setCounter] = useState(0);

 

  const clickHandler = () => {

    setCounter(counter + 1);

  };

 

  return (

    <>

      <button onClick={clickHandler}> Add </button>

      <h2> {counter} </h2>

    </>

  );

};

 

export default AddCounter;



The “AddCounter” component has a button and a counter below it with an initial value of 0. Whenever the button is clicked, the value of the counter increases by 1.

Now suppose we want another component with the same button and a counter but instead of increasing the value by 1, it increases the value by 100 on every button click. So we will break the application in such a way that the two components share the logic using a Higher-Order Component.

So let’s first create the function that will share the logic.
 

import { useState } from "react";

 

const HOC = (ExistingComponent, incrementBy) => {

  const HigherOrderComponent = () => {

    const [counter, setCounter] = useState(0);

 

    const clickHandler = () => {

      setCounter(counter + incrementBy);

    };

 

    return <ExistingComponent clickHandler={clickHandler} counter={counter} />;

  };

 

  return HigherOrderComponent;

};

 

export default HOC;




Let’s try to understand what is actually happening here.
  • The “HOC” function has two parameters - ExistingComponent and incrementBy.
  • In the “HigherOrderComponent”, a state is defined using the useState hook and “clickHandler” that increments the counter.
  • In one component, the counter increments by 1, and in another, it increments by 100. So we have an “incrementBy” value that is incoming from the components and this value is used in the “clickHandler” function.
  • In the end, the “clickHandler” and “counter” are passed as props to the “ExistingComponent”, meaning, the component with whom this entire logic is being shared.

Instead of using a class-based component, a functional component is used in this example.

Observe the following component.

import HOC from "./WithCounter";

 

const AddCounterByOne = ({ clickHandler, counter }) => {

  return (

    <>

      <button onClick={clickHandler}> Add </button>

      <h2> {counter} </h2>

    </>

  );

};

 

export default HOC(AddCounterByOne, 1);



“AddCounterByOne” increments the counter by one. This component does not have any logic. It uses the logic defined in the Higher-Order Component.

Similarly, observe the “AddCounterBy100” component.

import HOC from "./WithCounter";

 

const AddCounterByHundred = ({ clickHandler, counter }) => {

  return (

    <>

      <button onClick={clickHandler}> Add </button>

      <h2> {counter} </h2>

    </>

  );

};

 

export default HOC(AddCounterByHundred, 100);



Like the earlier component, “AddCounterByHundred” does not have any logic. Instead, it is using the logic defined in the Higher-Order Component.

This is a very basic example and it can be enhanced but our goal is to understand the basics of Higher-Order Components. In this example, we created two components - AddCounterByOne and AddCounterByHundred. Then we created a Higher-Order Component that shares the same logic with these two components.

Higher Order Components in React - Example Tutorial



Wrapping it up
Higher-Order Components in React are an advanced technique. In the beginning, you may find it tough to understand the concept but once you grab it, you will understand how useful Higher-Order Components can be. In this article, we discussed what are Higher-Order Components and what is the general way to work with them. Moreover, we created a simple application to understand the working of Higher-Order Components.

Other React.js  Articles and Tutorials you may like

Thanks for reading this article so far. If you like this React tutorial about lifecycle methods, please share it with your friends and colleagues. IF you have any questions or feedback, then please ask in the comments. 
 

No comments:

Post a Comment

Feel free to comment, ask questions if you have any doubt.