Using Recompose for writing elegant Higher Order Components

What is a HOC?

Higher Order Component (HOC) is a function which accepts a base component and returns a decorated component.

const hoc = BaseComponent => props => (
  <BaseComponent {...props} />
)

The component that the HOC returns is a stateless functional component. At its most basic form, the base component is rendered with all the supplied props. The props can be overridden by a variation of HOC which accepts an option or configuration.

const hoc = config => BaseComponent => props => (
  <BaseComponent {...props} {...config} />
)

The above HOC accepts a configuration which is more props.

const SinglePerson = hoc({ status: 'single' })(Person);
<SinglePerson age={21} />

Recompose

Recompose provides several higher order components which can be part of your React toolbox. I first came across the library while doing an enhancement for react-infinite-calendar. Since then, I have been a prolific user, using wherever it makes sense.

It is common to come across a list component in our apps. Consider a list of Order items Orders. Each order item has an order id and status. The status can be one of ‘Placed’, ‘Shipped’, ‘Delivered’. Usually, we want to filter the list by order status. We usually filter the orders and pass it to the Orders component.

const placedOrders = orders.filter(o => o.status === 'Placed');
<Orders items={placedOrders} />

With a HOC, the component can be rewritten as follows:

import { mapProps } from 'recompose';

const PlacedOrders = mapProps(({ items }) => {
  items: items.filter(o => o.status === 'Placed'),
  status: 'Placed'
})(Orders);

<PlacedOrders items={orders} />

The filtering logic is moved to a HOC which uses mapProps. mapProps takes a props object and returns a new props object. We filter the items prop. In addition, we insert a new status prop. Our HOC is not of much use if we cannot refactor reusable code.

const filterByStatus = status => mapProps(({items}) => {
  items: items.filter(o => o.status === status),
  status
});

const PlacedOrders = filterByStatus('Placed')(Orders);
const ShippedOrders = filterByStatus('Shipped')(Orders);
const DeliveredOrders = filterByStatus('Delivered')(Orders);

<PlacedOrders items={orders} />
<ShippedOrders items={orders} />
<DeliveredOrders items={orders} />

The above code illustrates the elegance of recompose. And how the HOC extracts reusable code.

Related Posts

Leave a Reply

Your email address will not be published.