What Are Higher-Order Components (HOCs) in React?
Learn what higher-order components are in React, how they wrap and enhance components, and when to use them over hooks.
Expected Interview Answer
A higher-order component is a function that takes a component as an argument and returns a new component with added behavior or props, letting you reuse cross-cutting logic like authentication checks or data injection across many components without duplicating that logic inside each one.
The pattern mirrors higher-order functions in plain JavaScript โ just as `map` takes a function and returns a new array-processing function, a HOC like `withAuth(Component)` takes a component and returns a wrapped version that adds a behavior, such as redirecting unauthenticated users, before rendering the original. Internally the HOC typically renders the wrapped component and passes through the original props plus any new ones it computes, following the "props in, enhanced props out" convention. Common gotchas include forgetting to copy static methods from the wrapped component onto the new one, and forgetting a stable `displayName` for debugging in React DevTools. Since the introduction of hooks, HOCs have become less common for pure logic-sharing (custom hooks are usually simpler for that), but they remain useful when you specifically need to wrap a component`s render output or inject props before the component ever mounts, such as with libraries like `react-redux``s `connect` or `react-router``s legacy `withRouter`.
- Shares cross-cutting behavior (auth, theming, logging) across many components
- Keeps the wrapped component`s own code free of that repeated logic
- Composable โ HOCs can be chained to layer multiple behaviors
- Works even for class components that predate hooks
AI Mentor Explanation
A higher-order component is like a stadium taking any regular player and returning that same player wearing an added layer โ say, a captain`s armband that grants extra decision-making authority โ without changing who the player fundamentally is underneath. The armband-wrapped player still does everything the original player did, plus the new captaincy behavior layered on top. You could even add a second layer, like a vice-captain designation, stacking behaviors. That take-a-player-return-an-enhanced-player pattern is exactly what a HOC does with a component.
Step-by-Step Explanation
Step 1
Define the enhancer function
Write a function withX(WrappedComponent) that accepts any component as its argument.
Step 2
Return a new component
Inside, return a new function component that renders WrappedComponent, passing through props.
Step 3
Inject or intercept behavior
Add new props, side effects, or conditional rendering (e.g. redirect if unauthenticated) before rendering.
Step 4
Preserve static methods and naming
Copy static methods and set a displayName so DevTools and consumers see a clear identity.
What Interviewer Expects
- Clear function-that-returns-a-component definition, distinct from a plain component
- Example of a real cross-cutting concern a HOC solves (auth, theming, data injection)
- Awareness of prop pass-through and static method copying pitfalls
- Comparison with custom hooks as the more modern alternative for pure logic sharing
Common Mistakes
- Confusing a HOC with a component that simply renders other components as children
- Forgetting to pass through the original props to the wrapped component
- Not copying static methods from the wrapped component, breaking library integrations
- Reaching for a HOC by default when a simpler custom hook would suffice
Best Answer (HR Friendly)
โA higher-order component is a function that takes a component and gives you back a new, upgraded version of it with some extra behavior built in โ like automatically checking if a user is logged in before showing the page. It is a way to reuse that kind of logic across many different screens without copying and pasting the same code everywhere.โ
Code Example
function withAuth(WrappedComponent) {
function AuthWrapped(props) {
const { user } = useAuth()
if (!user) {
return <Redirect to="/login" />
}
return <WrappedComponent {...props} user={user} />
}
AuthWrapped.displayName = `withAuth(${WrappedComponent.displayName || WrappedComponent.name})`
return AuthWrapped
}
// Usage: export default withAuth(Dashboard)Follow-up Questions
- How would you rewrite a withAuth HOC as a custom hook instead?
- What is prop collision and how do HOCs risk it?
- How do HOCs compose when you need to apply several of them to one component?
- What real-world libraries use the HOC pattern, and why did some move away from it?
MCQ Practice
1. What does a higher-order component take as input and return as output?
A HOC is a function accepting a component and returning a new wrapped component with added behavior.
2. What is a common mistake when writing a HOC?
Failing to spread props through breaks the wrapped component`s expected inputs.
3. Since hooks were introduced, when are HOCs still commonly useful?
HOCs remain useful for wrapping render output/props injection, even though hooks cover most pure logic-sharing cases now.
Flash Cards
What is a higher-order component? โ A function that takes a component and returns a new, enhanced component.
What must a HOC do with the original props? โ Pass them through (spread) to the wrapped component, plus any new ones it adds.
What should you copy onto the returned component? โ Static methods from the wrapped component, and set a clear displayName.
What largely replaced HOCs for logic sharing? โ Custom hooks, for most pure stateful-logic reuse cases.