Higher Order Components in React

In React, a Higher-Order Component (HOC) is a function that takes a component and returns a new component with additional props, state, or behavior. HOCs are a common pattern used for code reuse and for adding functionality to components without modifying them directly.

A Higher-Order Component is not a part of the React API. It is a pattern that emerges from React’s compositional nature. Essentially, an HOC is a function that takes a component and returns a new component with added functionalities.

HOCs are useful for:

Reusing Component Logic: Share common functionality across multiple components.

import React, { useState, useEffect } from "react";

// HOC to detect device type (mobile or desktop)
const withDeviceDetection = (WrappedComponent) => {
  return (props) => {
    const [isMobile, setIsMobile] = useState(false);

    useEffect(() => {
      const checkDevice = () => {
        if (typeof window !== "undefined") {
          const userAgent = window.navigator.userAgent;
          const mobileDevicePattern = /Android|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i;
          setIsMobile(mobileDevicePattern.test(userAgent));
        }
      };

      checkDevice();

      // Optional: Listen to window resize events to re-check device type
      const handleResize = () => checkDevice();
      window.addEventListener("resize", handleResize);

      // Cleanup event listener on unmount
      return () => window.removeEventListener("resize", handleResize);
    }, []);

    return <WrappedComponent isMobile={isMobile} {...props} />;
  };
};

export default withDeviceDetection;

The usage of HOC

import React from "react";
import withDeviceProtection from './withDeviceProtection'

const DeviceSpecificContent = ({ isMobile }) => {
  return (
    <div>
      {isMobile ? (
        <h1>Welcome Mobile User!</h1>
      ) : (
        <h1>Welcome Desktop User!</h1>
      )}
      <p>
        This content changes based on whether you are using a mobile device or a desktop browser.
      </p>
    </div>
  );
};

export default withDeviceProtection(DeviceSpecificContent);

Side Effects and State Management: Implement additional state management or lifecycle logic.

import React, { useEffect, useState } from 'react';

const withLoader = (WrappedComponent, url) => {
  return (props) => {
    const [data, setData] = useState(null);

    useEffect(() => {
      const getData = async () => {
        const res = await fetch(url);
        const data = await res.json();
        setData(data);
      };
      getData();
    }, []);

    if (!data) {
      return <div>...Loading</div>;
    }

    return <WrappedComponent {...props} dataPassedWithHOC={data} />;
  };
};

export default withLoader;

The usage of HOC

import React from 'react';
import withLoader from './withLoader';

        
const DataLoadingWithHoc = ({ dataPassedWithHOC }) => {
  return (
    <div>
      <h1>Data Loading with HOC</h1>
        <p>
          {dataPassedWithHOC.map((post) => {
            return (
              <div key={post.id}>
                <h2>{post.title}</h2>
                <p>{post.body}</p>
              </div>
              );
          })}
        </p>    
    </div>
  );
};
        
export default withLoader(DataLoadingWithHoc, 'https://jsonplaceholder.typicode.com/posts?_page=1');

Code Organization: Separate concerns by encapsulating logic outside of components.

import React, { useState } from "react";

// HOC for toggling visibility
const withToggleVisibility = (WrappedComponent) => {
  return (props) => {
    const [isVisible, setIsVisible] = useState(false);

    const show = () => setIsVisible(true);
    const hide = () => setIsVisible(false);
    const toggle = () => setIsVisible((prev) => !prev);

    return (
      <>
        {/* Pass visibility state and toggle methods as props */}
        <WrappedComponent
          isVisible={isVisible}
          show={show}
          hide={hide}
          toggle={toggle}
          {...props}
        />
      </>
    );
  };
};

export default withToggleVisibility;

The usage of HOC

import React from "react";
import withToggleVisibility from './withToggleVisibility';

const ToggleableContent = ({ isVisible, show, hide, toggle }) => {
  return (
    <div>
      <h2>Visibility Toggle Example</h2>
      <button onClick={toggle}>
        {isVisible ? "Hide Content" : "Show Content"}
      </button>
      {isVisible && <p>This content is toggled by clicking the button above.</p>}
    </div>
  );
};

export default withToggleVisibility(ToggleableContent);

Manipulating Props: Add, modify, or filter the props passed to components.

import React from "react";

// HOC to manipulate props
const withModifiedProps = (WrappedComponent) => {
  return (props) => {
    // Add a new prop
    const newProp = { addedProp: "This is a new prop added by the HOC" };

    // Modify an existing prop
    const modifiedProps = {
      ...props,
      message: props.message ? props.message.toUpperCase() : "DEFAULT MESSAGE",
    };

    // Filter out unwanted props
    const { unwantedProp, ...filteredProps } = modifiedProps;

    // Combine all props
    const combinedProps = { ...filteredProps, ...newProp };

    return <WrappedComponent {...combinedProps} />;
  };
};

export default withModifiedProps;

The usage of HOC

import React from "react";
import withModifiedProps from './withModifiedProps'

const DisplayProps = ({ message, addedProp }) => {
  return (
    <div>
      <h2>Displaying Modified Props</h2>
      <p>{message}</p>
      <p>{addedProp}</p>
    </div>
  );
};

export default withModifiedProps(DisplayProps);
All BlogsGo To Top