The Higher-Order Component Pattern in React

What are Higher-Order components, and how it solves

What are Higer order components

Aside from the name sounding like it came from star wars. A higher-order component (HOC) is an advanced technique in React for reusing component logic, and computed state.

It solves the problem of accessing logic, and computed states that lives in a separate component without rewriting, refetching, or lifting them up. HOCs solve it by pre-processsing and modifying the props before sending them to the consuming component.

HOCs are comparable to dependency injections

  • They are not a part of the view system.
  • Computes, and modifies state before sending it to a consuming component.

If a component requested for a data. Our HOC can cache that data to avoid refetching it in every instance of our HOC.

Example problem

A problem where we fetched the user in Navbar component but we need it in our MainContent component

Let's say we need to display the user's fullName(computed firstName + lastName) in both the Navbar and MainContent components. But we fetched the user data within the Navbar component.

How are we going to access that data on our MainContent component?

There are 3 ways this can be solved:

  1. Refetch the user data, and recompute the user's fullName in the MainContent component. ❌
  2. Lift the state up. Well... This is an HOC article so we're not doing this.
  3. Create an HOC to compute, and fetch data then consume it on our components. ✅
export const Navbar = ({ name, color }) => {
  return <div>{name}</div>
}

export const MainContent = ({ name }) => {
  return <div>Hello {name}</div>
}

export const withName = (Component) => (props) => {
  const user = {
    firstName: 'Roman',
    lastName: 'Munar'
  }

  const userFullName = `${user.firstName} ${user.lastName}`

  return <Component {...props} name={userFullName} />
}

export const MainContentWithName = withName(MainContent)
export const NavbarWithName = withName(Navbar)

// Later on...

// No need to pass a name prop
<NavbarWithName color='#000' />
// Can still be used with custom name prop
<Navbar name='Sup' color='#000' />

Caveats

Using HOCs with Typescript can be challenging because we are applying some props on our own, and some passed unto the component. So avoid using components with and without HOCs If you're using Typescript.

Conclusion

Useful for cross cutting logic, and computed states. at some point though you might want to use atoms. As you'll soon face computed states from other HOCs that would warrant you to wrap an HOC with another HOC which is hard to read, and change.

Tip

If you liked this article I'm sure you'll like the article I wrote about the renderProps Pattern even more.