Higher Order Components in a React Hooks World
Albert Chu
1593

The Value of Prop Mutation with Higher-order Components

Photo by Kelly Sikkema on Unsplash

Some of the reasons why someone would use an HoC to transform input for a component is to keep the component logic simple and for modular reusability. In this sense, it can separate concerns so that any given component and the way its data is processed are easy to test independently.

Simple Example

You need to render a date time object of structure:

{
year: 2018,
month: 1,
day: 1
}

The component can be simple. You just pass in this object, and all it needs to worry about is how to render each part of this date. Now consider if you need to render from multiple sources. In one usage, you are rendering Date.now(), and in another usage, it is the response from a GET call, wrapped in { data: {...} }. it is nested inside another object.

When separating the data transformation logic into an HoC, all you need is to enhance the simple functional component with whatever data transformation logic you need.

All different transformation logic can be tested separately from the functional component (which might not even need testing if the rendering logic is simple enough).

Fun Example

Here’s a more complex example (that I’ve actually used at work before):
Say you want to render a dropdown component. In one use-case: you are rendering nested objects by their keys. In another use-case, you need to render an input array. The component will already be complex enough without needing to consider how the data is processed. It needs to consider:

  • How to render the nested menu items
  • Passing through the onChange callback,
  • Maybe some custom click-away logic.
  • Styling
  • Animations
  • Debouncing
  • ETC

Now consider if you need to render dropdowns from a dozen different sources each with a slightly different data format like these ones. You can write the generic dropdown component once, test the hell out of it and can reuse all that well-tested code as many times as you need, while only adding tests for data transformation logic in each new use-case.

In my usages with this problem, I made a generic dropdown component which takes an array of objects of type:

{
id: 'valuekey',
displayText: 'Value Text'
}

and an onChange function with the signature: ({id, displayText}) => {...} which is clear and useful regardless of what content is in the dropdown.

On a slight tangent: all those other bullet points of functionality that the generic dropdown component needs can also be written in a composable way with higher-order components. Whether all of them should is another question, but in each case, they would always benefit from the advantages of concern separation, and improved ability to isolate functionality for testing.

Thanks Roger Wakeman for the idea to elaborate on this. This is an elaboration to the prop mutation section in my other article Higher Order Components in a React Hooks World