Higher Order Components (HoC) in React can be simple to use and test. If you haven’t read about HoC’s and how and why they’ve replaced mixins, check out this great Medium post by Dan Abramov.
Most of the resources and examples that I found online about higher order components are complex, and don’t include a testing solution. This is a super simple example designed to demonstrate how we can generalize React components using Higher Order Components and unit test them. We will be using ES6 syntax and Enzyme to test.
Let’s start the example with two Components, a
UserList and a
PokemonList. In this naive example, the two lists have a different number of columns, and different column headers, but share the same selection behavior.
The code to fetch the data is unsharable for… reasons. Let’s just pretend, ok? Looking at the rest of the class, however, it’s painfully obvious that we need to extract this shared code.
Higher Order Components
Now, let’s extract the selection code! In the example below, have extracted the common code into a higher order component called
ListWrapper. The HoC is created inside a function that accepts another component. Inside the function, the HoC is defined and returned.
onSelect used to be state values on the original components, but are now props that are passed from the
ListWrapper. In the entry file, we are now calling the
listWrapper function on our components and rendering that into the DOM rather than invoking render on our component directly. Do not wrap your components before this! It won’t allow you to unit test all parts individually.
That’s it, really. What’s that? You want to unit test your code you say? That’s what I like to hear!
To unit test these components, we will use a AirBnB’s shallow rendering library, Enzyme.
Again, I have not wrapped the list components before exporting them above. This allows us to test the HoC and component behavior separately.
Testing the HoC
In order to unit test the
ListWrapper, I create a
MockListComponent with no behavior in the before block. I wrap the dummy component with using the
listWrapper function, and then use Enzyme’s
shallow to shallow render it into the DOM.
The rest is just Jasmine.
Testing the Components
Because we didn’t wrap the list components, we can now unit test them as we normally would. We have to pass in our props before we render the component because we are enforcing propTypes.
I added a sample spec just to demo how we would use the
onSelect spy if we needed to.
Easy and Testable
Higher Order Components are fairly easy to use and testable. Just make sure you actually need one before using it. Trying to wedge in a HoC where it’s not needed can be a painful process.
Good luck and happy coding!