REACT Higher-Order Component

What is a Higher-Order Component (HOC)?

A Higher-Order Component (HOC) is a function that takes a component as input and returns a new enhanced component. HOCs allow code reuse, logic abstraction, and component composition in React.

HOCs follow this pattern:

const EnhancedComponent = withSomething(OriginalComponent);

1. Why Use HOCs?

  • Code Reusability: Extract shared logic into a single function.
  • Separation of Concerns: Keep components focused on UI while HOCs handle logic.
  • Enhancing Components: Add features like authentication, theming, logging, etc.

2. Basic Example of an HOC

Let’s create an HOC that adds extra props to a component.

Step 1: Create the HOC

import React from "react";

const withExtraInfo = (WrappedComponent) => {
  return (props) => {
    return <WrappedComponent extraInfo="This is extra info!" {...props} />;
  };
};

export default withExtraInfo;

Step 2: Use the HOC in a Component

import React from "react";
import withExtraInfo from "./withExtraInfo";

const MyComponent = ({ extraInfo }) => {
  return <h1>{extraInfo}</h1>;
};

export default withExtraInfo(MyComponent);

βœ… What happens? The MyComponent now automatically receives extraInfo from the HOC.

3. Practical Use Cases of HOCs

A. Authentication HOC (Protect Routes)

const withAuth = (WrappedComponent) => {
  return (props) => {
    const isAuthenticated = true; // Simulating authentication

    if (!isAuthenticated) {
      return <h2>Please log in to access this page.</h2>;
    }

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

// Usage:
const Dashboard = () => <h1>Welcome to Dashboard</h1>;
export default withAuth(Dashboard);

B. Logging HOC (Track Component Rendering)

const withLogger = (WrappedComponent) => {
  return (props) => {
    console.log(`Component ${WrappedComponent.name} is rendering`);
    return <WrappedComponent {...props} />;
  };
};

// Usage:
const Profile = () => <h1>My Profile</h1>;
export default withLogger(Profile);

Every time Profile renders, it logs to the console!

 

C. Fetch Data HOC

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

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

    useEffect(() => {
      fetch(url)
        .then((res) => res.json())
        .then((data) => setData(data));
    }, []);

    return data ? <WrappedComponent data={data} {...props} /> : <h3>Loading...</h3>;
  };
};

// Usage:
const UsersList = ({ data }) => (
  <ul>
    {data.map((user) => (
      <li key={user.id}>{user.name}</li>
    ))}
  </ul>
);

export default withDataFetching("https://jsonplaceholder.typicode.com/users")(UsersList);

The UsersList component automatically gets user data!

4. HOCs vs. Render Props vs. Hooks

Feature HOCs Render Props Hooks
Code Reuse βœ… Yes βœ… Yes βœ… Yes
Readability ❌ Can get messy βœ… Better βœ… Best
Performance ⚠️ Can cause re-renders βœ… More control βœ… Efficient
Modern React 🚫 Less recommended βœ… Okay βœ… Best choice

πŸ‘‰ Hooks (like useEffect, useContext) have mostly replaced HOCs in modern React, but HOCs are still useful in class-based components!

5. When to Use HOCs?

βœ… Use HOCs when:

  • You need to reuse logic across multiple components.
  • Your project uses class components.
  • You want to abstract complex logic (e.g., authentication, permissions, logging).

❌ Avoid HOCs when:

  • You are using modern React with hooks (useEffect, useContext).
  • You have only a single-use case (directly placing logic in the component may be simpler).