React Higher Order Components (HOC)

Reusing component logic with HOC pattern

🔄 What is a Higher Order Component?

A Higher Order Component (HOC) is a function that takes a component and returns a new enhanced component. It's a pattern for reusing component logic across multiple components without repeating code.


// Simple HOC example
const withGreeting = (Component) => {
  return (props) => (
    <div>
      <h2>Welcome!</h2>
      <Component {...props} />
    </div>
  );
};
                                    

Key HOC Concepts

🔧

Reusability

Share logic between components

const Enhanced = withAuth(MyComponent);
📦

Composition

Wrap components with extra features

withLoading(withAuth(Component))
🎯

Props Injection

Add new props to components

<Component {...props} newProp={value} />
🛡️

Protection

Add authentication or validation

if (!isAuth) return <Login />;

🔹 Basic HOC Example

A Higher Order Component is a function that wraps another component to add functionality. Here's a simple example that adds a loading state to any component.

// HOC that adds loading functionality
const withLoading = (Component) => {
  return ({ isLoading, ...props }) => {
    if (isLoading) {
      return <div>Loading...</div>;
    }
    return <Component {...props} />;
  };
};

// Original component
const UserProfile = ({ name }) => (
  <div>
    <h3>User: {name}</h3>
  </div>
);

// Enhanced component with loading
const UserProfileWithLoading = withLoading(UserProfile);

// Usage
<UserProfileWithLoading isLoading={false} name="John" />

Output:

User: John

🔹 HOC with Props Manipulation

HOCs can modify, add, or remove props before passing them to the wrapped component. This is useful for data transformation or adding default values.

// HOC that adds timestamp to props
const withTimestamp = (Component) => {
  return (props) => {
    const timestamp = new Date().toLocaleTimeString();
    return <Component {...props} timestamp={timestamp} />;
  };
};

// Component that receives timestamp
const Message = ({ text, timestamp }) => (
  <div>
    <p>{text}</p>
    <small>Sent at: {timestamp}</small>
  </div>
);

// Enhanced component
const MessageWithTimestamp = withTimestamp(Message);

// Usage
<MessageWithTimestamp text="Hello World!" />

Output:

Hello World!

Sent at: 10:30:45 AM

🔹 Authentication HOC

A common use case for HOCs is protecting routes or components that require authentication. The HOC checks if the user is logged in before rendering the component.

// HOC for authentication
const withAuth = (Component) => {
  return (props) => {
    const isAuthenticated = true; // Check auth status
    
    if (!isAuthenticated) {
      return <div>Please log in to continue</div>;
    }
    
    return <Component {...props} />;
  };
};

// Protected component
const Dashboard = () => (
  <div>
    <h2>Dashboard</h2>
    <p>Welcome to your dashboard!</p>
  </div>
);

// Protected dashboard
const ProtectedDashboard = withAuth(Dashboard);

// Usage
<ProtectedDashboard />

Output (when authenticated):

Dashboard

Welcome to your dashboard!

🔹 Composing Multiple HOCs

You can combine multiple HOCs to add different functionalities to a single component. This creates a powerful composition pattern for building complex features.

// Multiple HOCs
const withLoading = (Component) => ({ isLoading, ...props }) => 
  isLoading ? <div>Loading...</div> : <Component {...props} />;

const withError = (Component) => ({ error, ...props }) => 
  error ? <div>Error: {error}</div> : <Component {...props} />;

// Base component
const DataDisplay = ({ data }) => (
  <div>Data: {data}</div>
);

// Compose multiple HOCs
const EnhancedDataDisplay = withLoading(withError(DataDisplay));

// Usage
<EnhancedDataDisplay 
  isLoading={false} 
  error={null} 
  data="Success!" 
/>

Output:

Data: Success!

🔹 HOC Best Practices

✅ Do's:

  • Pass all props: Use {...props} to forward props
  • Naming convention: Start HOC names with "with"
  • Keep it simple: One responsibility per HOC
  • Display name: Set displayName for debugging

❌ Don'ts:

  • Don't mutate: Never modify the original component
  • Don't use in render: Create HOCs outside components
  • Don't copy statics: Remember to copy static methods

🧠 Test Your Knowledge

What does a Higher Order Component return?