Higher Order Components

Gabriel Castro
3 min readMar 9, 2021

--

If there is anything I have learned about coding in React is that things can get really redundant really fast. Such as creating your components, setting up your arrow functions, setting your state and returning your output. All these lines of code get real cumbersome, and the bigger your applications become the more and more components you have that can benefit from others. Enter Higher Order Components, these components allow developers to reuse a components logic to create a different output.

Alright, so now we have a basic understanding…what does this look like in practice? Well lets look a simple example. Lets say we are building a new application, and one of our components we are creating is a counter, it simply counts each time a button is clicked. We might build out something like this…

import React, { useState } from 'react'const ButtonCounter = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1)
}
return (
<div>
<p>{count}<p>
<button onClick={increment}>Increment</button>
<div>
);
}
export default ButtonCounter

This is great, simple counter to help keep track of a button click, but as our application grows lets say we want to track other things. For example lets say we want to keep track of every time a header is moused over. That’s no problem…

import React, { useState } from 'react'const HoverCounter = () => {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1)
}
return (
<div>
<p> {count} </p>
<h2 onMouseOver={increment}> Hovered {count} times </h2>
</div>
);
}
export default HoverCounter

Alright, no issue… little redundent but doable. Now lets say we are continuing to build out this application but now we have a link we need to count each time. Welp! here we are again, we could keep going on this path of creating new components each time with a counter and then set up the unique return value; in this never ending cycle of redundancy… or we can evolve our tactics.

Right now our App looks something like this..

import React, { Component } from 'react'
import './App.css'
import ButtonCounter from './components/ButtonCounter'
import HoverCounter from './components/HoverCounter'
function App() {return (
<ButtonCounter />
<HoverCounter />
);
}
export default App;

returning the two components we built earlier. So how can we now go about making the redundancy in our two components reusable? Well with a Higher Order Component we can do something like this…

Higher Order Component:

import React from 'react'const withCounter = WrappedComponent => {
class WithCounter extends React.Component {
state = {
count: 0 //initial state being handled
}
increment = () => {
this.setState(preState => {
return { count: prevState.count + 1 } //increment count by 1
)}
}
render() {
return (
<WrappedComponent
count={this.state.count} //setting state
increment={this.increment}
/>
)
}
}
return WithCounter //returning our new component
}
export default withCounter

We can now go ahead and remove our duplicate code in our other components, simply exporting our HOC(Higher Order Component) and passing in our components while also passing down props we can provide them with the same functionality and less duplicate code.

ButtonCounter Component:

import React, { useState } from 'react'
import withCounter from './withCounter'
class ButtonCounter extends React.Component {render() {
const { count, increment } = this.props //de-structuring
return (
<button onClick={increment}>
Clicked {count} times
</button>
)
}
}
export default withCounter(ButtonCounter)

HoverCounter Component:

import React, { useState } from 'react'
import withCounter from './withCounter'
class HoverCounter extends React.Component {render() {
const { count, increment } = this.props //de-structuring
return (
<div>
<p> {count} </p>
<h2 onMouseOver={increment}>
Hovered {count} times </h2>
</div>
)
}
}
export default withCounter(HoverCounter)

Our state is now handled in the HOC with our logic, while our regular component simply handle the output we want.

--

--

Gabriel Castro
Gabriel Castro

Written by Gabriel Castro

Full Stack, Software Engineer. Focus in Rails, JavaScript and React.

No responses yet