Higher-Order Components (HOC)
A higher-order component is a function that takes a component and returns a new component with enhanced behavior. It's the React equivalent of a decorator pattern: withAuth(Dashboard) returns an AuthenticatedDashboard.
An HOC is a phone case — it wraps around your phone (component), adds features (grip, card holder), but the phone inside works the same. Stack too many cases and it gets unwieldy.
HOCs wrap a component, injecting props from shared logic. Examples: withRouter (React Router v5), connect (Redux), withTheme. HOCs should pass through all received props to the wrapped component and hoist static methods using hoist-non-react-statics. They compose well: compose(withAuth, withTheme, withRouter)(MyComponent). The drawback is 'wrapper hell' in DevTools and potential prop name collisions.
HOCs are largely replaced by hooks in modern React, but understanding them is important for legacy codebases and for the pattern itself. Key rules: don't mutate the original component (create a new one), forward refs with React.forwardRef, and copy over displayName for debugging. HOCs break if applied inside render (creates new component type each render, causing remount). Always apply HOCs outside the component definition. TypeScript generic HOCs are notoriously hard to type correctly.
HOCs are functions that wrap a component to inject additional behavior via props. They were the go-to pattern before hooks for cross-cutting concerns like auth, theming, and routing. I still encounter them in legacy codebases and Redux's connect. For new code, I prefer hooks because they avoid wrapper hell, prop collisions, and the DevTools debugging challenges of deeply nested HOCs.
Applying an HOC inside a render method creates a new component type on every render, causing the entire subtree to unmount and remount. Always apply HOCs at the module level.