Higher‑Order Components: The Legacy Pattern You'll Still Meet
Wrap a component to inject extra props. Useful to understand, even if hooks are preferred today.
A higher-order component is a function that takes a component and returns a new one with extra behavior or props. Hooks replaced most of them, but I still meet HOCs in older codebases and some libraries, so I keep the pattern in my head.
Passing user by hand
Say UserProfile needs a user prop and I don’t want to thread it through every usage.
function UserProfile({ user }) {
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
function App() {
const user = { name: "John Doe", email: "john@example.com" };
return (
<div>
<h1>Higher-Order Components</h1>
<UserProfile user={user} />
</div>
);
}
export default App;
Passing user manually at every call site works. It’s just noisy.
withUser wraps it once
So I write a withUser HOC that returns an enhanced component.
function withUser(Component) {
const user = { name: "John Doe", email: "john@example.com" };
return function EnhancedComponent(props) {
return <Component {...props} user={user} />;
};
}
function UserProfile({ user }) {
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
);
}
const EnhancedUserProfile = withUser(UserProfile);
function App() {
return (
<div>
<h1>Higher-Order Components</h1>
<EnhancedUserProfile />
</div>
);
}
export default App;
The user object now lives inside the HOC, and App just renders the enhanced component.
Stripped of the surrounding JSX, before.
function App() {
const user = { name: "John Doe", email: "john@example.com" };
return <UserProfile user={user} />;
}
After.
const EnhancedUserProfile = withUser(UserProfile);
<EnhancedUserProfile />
Working with them today
Name HOCs by behavior, withAuth or withFeatureFlags. Preserve static properties if something relies on them; many libraries ship helpers. For new code, hooks. A HOC earns its place only when a library requires one.