What are Higher‑Order Components in React?

Hero image for What are Higher‑Order Components in React? Image by Mvrkle.
Hero image for 'What are Higher‑Order Components in React?' Image by Mvrkle.

HigherOrder Components (sometimes referred to as HOCs) are a powerful pattern in React that allow us to enhance and reuse component logic across different parts of our application. They provide a way to wrap components with additional functionality without modifying their internal structure.

In this article, I will explore what HigherOrder Components are, how they work, and when to use them. By the end, you should have a solid understanding of how HOCs can improve code reusability and maintainability in React applications.


What is a Higher‑Order Component?

A HigherOrder Component (HOC) is a function which takes a component as an argument and returns a new, enhanced version of that component. This pattern allows for the reuse of logic (and extension) across multiple components without duplicating code.

Basic Syntax of an Hoc

Here's a rough outline of what an HOC looks like in a basic form:

const withLogger = <P extends object>(WrappedComponent: React.ComponentType<P>) => {  return (props: P) => {    console.log("Rendering component with props:", props);    return <WrappedComponent {...props} />;  };};

It looks a bit ugly with TypeScript, but here, withLogger is a function which wraps a given component and logs its props every time it renders. This is an example of how an HOC can add crosscutting concerns (such as logging) to multiple components without modifying their implementation directly.


Why Use Higher‑Order Components?

HOCs help with:

  • Code Reusability

    – Share logic between multiple components without duplicating code.
  • Separation of Concerns

    – Keep UI and logic separate by encapsulating behaviour.
  • Enhancing Components

    – Modify or extend component functionality dynamically.

Common use cases for HOCs include authentication, data fetching, logging, and UI enhancement, which I'll go into more detail about below.


Common Use Cases for Hocs

1. Adding Authentication Logic

const withAuth = <P extends object>(WrappedComponent: React.ComponentType<P>) => {  return (props: P) => {    const isAuthenticated = Boolean(localStorage.getItem("token"));    return isAuthenticated ? <WrappedComponent {...props} /> : <p>Please log in</p>;  };};

This HOC checks whether a user is authenticated by looking for a token in local storage. If the user is authenticated, it allows the wrapped component to render; otherwise, it displays a message prompting them to log in. This pattern is useful for protecting routes or sections of an application that require authentication.

2. Fetching Data in an Hoc

const withData = <P extends { data?: any }>(WrappedComponent: React.ComponentType<P>, url: string) => {  return (props: Omit<P, "data">) => {    const [data, setData] = React.useState(null);    React.useEffect(() => {      fetch(url)        .then(response => response.json())        .then(setData);    }, [url]);    return <WrappedComponent {...(props as P)} data={data} />;  };};

Here, we have an HOC which fetches data from a specified URL and injects it as a prop (data) into the wrapped component. By keeping the datafetching logic separate, multiple components can share the same functionality without duplicating code. It also meant that there's only one place you need to update that URL if your data source should change (although I would argue that should be usually be in an environmental variable or a central const file anyway).

3. Conditionally Applying Styles

const withTheme = <P extends object>(WrappedComponent: React.ComponentType<P>) => {  return (props: P) => {    const theme = "dark";    return (      <div className={theme}>        <WrappedComponent {...props} />      </div>    );  };};

In this example, the HOC wraps a component with a div when then applies a theme class. This allows global styling to be dynamically applied to components without modifying their internal implementation. It's particularly useful for adding themes or layoutspecific styling across different parts of an application or where the same components are being used across different brands or themes.


Hocs vs. Hooks: Which Should You Use?

With the introduction of React Hooks, some of the patterns previously implemented with HOCs can now be replaced with imported hooks. However, HOCs are still useful when:

  • You need to wrap class components (since hooks are only for functional components).
  • The same logic needs to be applied across multiple unrelated components.
  • You want to enforce patterns at a higher level of abstraction.

With that said, in most modern React applications, hooks are preferred over HOCs due to their simpler and more readable nature.


Wrapping up

HigherOrder Components provide a structured way to enhance React components by wrapping them in reusable logic. While HOCs are still valuable in some instances, React Hooks have largely replaced them in modern development.

Key Takeaways

  • HOCs are functions that take a component and return an enhanced version of it.
  • They promote code reusability, separation of concerns, and component enhancement.
  • Common use cases include authentication, data fetching, and styling.
  • Hooks have replaced many HOC use cases in modern React applications.

Understanding HOCs will help you maintain and refactor legacy React applications while applying the right patterns in different situations.


Categories:

  1. Development
  2. Front‑End Development
  3. Guides
  4. JavaScript
  5. React