Posts

Higher-Order Components (HOCs) in React

January 9, 2025
React provides several patterns to reuse component logic—and Higher-Order Components (HOCs) are a classic yet powerful one. In this hands-on post, we will use HOCs to build a reusable Logger HOC that logs when a component mounts, updates, and unmounts. A Higher-Order Component is simply a function that:
  • Takes a component as input
  • Returns a new component with extended functionality
HOC Example
const withSomething = (Component) => {
  return (props) => <Component {...props} />;
};
Let’s say we want to debug component behavior in development. We can log:
  • When the component mounts
  • When it unmounts
  • When it updates
  • What props are passed
Base Component
type UserProps = {
  name: string;
};

function UserCard({ name }: UserProps) {
  return <div>Hello, {name}!</div>;
}
Here’s the enhanced version with full lifecycle logs:
withLogger HOC
import { useEffect } from 'react';

function withLogger<P>(WrappedComponent: React.ComponentType<P>) {
  const ComponentWithLogger = (props: P) => {
          useEffect(() => {
              // Log data on component mount
              console.log(`Component ${WrappedComponent.name} mounted.`);
              return () => {
                  // Log data on component unmount
                  console.log(`Component ${WrappedComponent.name} unmounted.`);
              };
          }, []);


          console.log(`[Logger] Props:`, props);

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

ComponentWithLogger.displayName = `withLogger(${WrappedComponent.displayName || WrappedComponent.name})`;
return ComponentWithLogger;
}
✅ Includes:
  • mount, unmount logs
  • Generic props type inference
  • Named component for DevTools
Using the HOC
const UserCardWithLogger = withLogger(UserCard);

function App() {
  const [name, setName] = useState("Alice");

  return (
          <div>
              <UserCardWithLogger name={name} />
              <button onClick={() => setName("Bob")}>Change Name</button>
          </div>
  );
}
Expected Console Output:
Console Output
Component UserCard mounted.
[Logger] Props: { name: 'Alice' }
Component UserCard updated.
[Logger] Props: { name: 'Bob' }
Component UserCard unmounted.
  • Easy to apply across components
  • Non-invasive (original component logic stays pure)
  • Supports both class and function components
  • Great for debugging, analytics, performance tracking
  • 🔐 withAuth – redirect if not authenticated
  • 📊 withTracking – send metrics to analytics
  • 🚀 withFeatureFlag – hide/show features
  • 🛠️ withErrorBoundary – wrap with error fallback
HOCs are still a valuable pattern in React for cross-cutting concerns like logging. With just a few lines of code, you can wrap components and inspect their lifecycle without altering their core logic. The withLogger HOC we built logs:
  • Mount
  • Update
  • Unmount
  • Props on every render
Want to keep learning reusable React patterns? Check out:
On this page