Using Recompose to write clean Higher Order Components
Tags: react, javascript, higherordercomponent, webdev
Published: 2019-07-08 17:14:28

---
title: Using Recompose to write clean Higher Order Components
published: true
tags: react,javascript,higher-order-component,web-development
canonical_url: https://blog.logrocket.com/using-recompose-to-write-clean-higher-order-components-3019a6daf44c
---

### Using Recompose to write clean Higher-Order Components

![](https://cdn-images-1.medium.com/max/1024/1*YwgQkhqNcJZGgym5I-VSMQ.png)

If you like keeping things simple in React, by creating small components with functional component syntax and by using them as pieces to create bigger ones, [_Recompose_](https://github.com/acdlite/recompose) can help you to do the same with Higher-Order Components (HOCs).

With _Recompose_ it is easier to create small Higher-Order Components that can be composed into more complex ones. With the approach encouraged by _Recompose_, you won’t need more Class syntax to create React components.

But before going into details, let’s start reviewing some concepts…

[![](https://cdn-images-1.medium.com/max/1024/1*GPjaPKNNUYHU8EsA3Z0JGA.png)](https://logrocket.com/?cid=banner_a)

### Higher Order Functions

In Javascript, we have a special type of functions, called **Higher-Order Functions:**

> A [Higher-Order Function](https://en.wikipedia.org/wiki/Higher-order_function) is a function that deal with other functions, either because it receives them as parameters (to execute them at some point of the body’s functions) or because it returns a new function when it’s called or both.
```jsx
const sum = (a, b) => a + b
const multiplication = (a, b) => a * b

// Our Higher-Order Function
const getResultOperation = op => (a, b) => `The ${op.name} of ${a} and ${b} is ${op(a, b)}`

const getSumResult = getResultOperation(sum)
const getMultiplicationResult = getResultOperation(multiplication)

console.log( getSumResult(2, 5) ) // The sum of 2 and 5 is 7 
console.log( getMultiplicationResult(2, 5) ) // The multiplication of 2 and 5 is 10 
```
*getResultOperation*

In the example above, getResultOperation receives a function and returns a new one. So it is a _Higher-Order Function._

> _The most popular_ Higher-Order Functions _in Javascript are the array methods_ [_map_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)_,_ [_filter_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) _or_ [_reduce_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)_. They all apply some function_ passed as a parameter _over the elements of the array to get something as a result_

### Higher-Order Components

In React, we have the equivalent of Higher-Order Functions but for components, the so-called Higher-Order Components.

> A [Higher-Order Component](https://reactjs.org/docs/higher-order-components.html) is a function that takes a component and returns a new component.

When are the Higher-Order Components useful? Well, mostly to reuse the logic involving behavior across components. Let’s explain this with the following scenario.

Let’s assume we already have a component Button
```jsx
const Button = ({ type = "primary", children, onClick }) => (
  <button className={`btn btn-${type}`} onClick={onClick}>
    {children}
  </button>
);
```
And we want to create another ButtonWithTrack based on this Button (same props on Button should also work on ButtonWithTrack and same styles applied) but with improved behavior (like keeping track of the times it has been clicked and displaying this value on the button itself).

To do this we can do…
```jsx
import Button from "./Button";

class ButtonWithTrack extends Component {
  constructor(props) {
    super(props);
    this.state = {
      times: 0
    };
  }
  handleClick = e => {
    let { times } = this.state;
    const { onClick } = this.props;
    this.setState({ times: ++times });
    onClick && onClick();
  };
  render() {
    const { children } = this.props;
    const { times } = this.state;
    return (
      <span onClick={this.handleClick}>
        <Button type={times > 5 ? "danger" : "primary"}>
          {children} <small>{times} times clicked</small>
        </Button>
      </span>
    );
  }
}
```
We have reused the original Button so everything ok for now.

Let’s take another component Link:
```jsx
const Link = ({ type = "primary", children, href, onClick }) => (
  <a style={styles} className={`badge badge-${type}`} href={href} onClick={onClick}>
    {children}
  </a>
);
```
And we want to add the exact same behavior we added to our Button.

What to do then? Should we repeat 90% of the code in 2 files? Or is there a way we can take out the logic added to ButtonWithTrack in a way it can be applied to both Button and Link components?

**Higher-Order Components** to the rescue!!

To solve this problem, we can create a Higher-Order Component, this is, a function that takes one component and returns the enhanced version of that component with the behavior we want.

For example, we can do this:
```jsx
const withClickTimesTrack = WrappedComponent =>
  class extends Component {
    constructor(props) {
      super(props);
      this.state = {
        times: 0
      };
    }
    handleClick = e => {
      e.preventDefault();
      let { times } = this.state;
      const { onClick } = this.props;
      this.setState({ times: ++times });
      onClick && onClick();
    };
    render() {
      const { children, onClick, ...props } = this.props;
      const { times } = this.state;
      return (
        <span onClick={this.handleClick}>
          <WrappedComponent
            type={times > 5 ? "danger" : "primary"}
            {...props}
          >
            {children} <small>({times} times clicked)</small>
          </WrappedComponent>
        </span>
      );
    }
  };
```
So then, we can simplify the creation of the componentButtonWithTrack from Button by using the withClickTimesTrack HOC like this:
```jsx
import withClickTimesTrack from "./hoc/withClickTimesTrack";

const Button = ({ type = "primary", children, onClick }) => (
  <button className={`btn btn-${type}`} onClick={onClick}>
    {children}
  </button>
);

const ButtonWithTrack = withClickTimesTrack(Button);
```
And also now, we can easily apply the same enhancement to other components like Link:
```jsx
import withClickTimesTrack from "./hoc/withClickTimesTrack";

const Link = ({ type = "primary", children, href, onClick }) => (
  <a style={styles} className={`badge badge-${type}`} href={href} onClick={onClick}>
    {children}
  </a>
);
const LinkWithTrack = withClickTimesTrack(Link);
```
Cool, isn’t it?

But we can think this HOC add too many behaviors at the same time (handler, state & new UI).

Wouldn’t it be better if we split the logic behind the HOC into smaller parts?

### Composing HOCs

Ok, its decided! We want to have these three behaviors of the HOC isolated so we can reuse them independently in other components:

- Add times state
- Add custom handleClick
- Display the times state inside the element

To do this we can create 3 HOCs where each one will add a specific behavior…
```jsx
const withStateTimes = WrappedComponent =>
  class extends Component {
    constructor(props) {
      super(props);
      this.state = {
        times: 0
      };
    }
    setTimes = (times) => {
      this.setState({ times })
    }
    render() {
      const { times } = this.state
      const { setTimes } = this
      return (
        <WrappedComponent times={times} setTimes={setTimes} { ...this.props } />
      );
    }
  };
```
*withStateTimes.js*

```jsx
const withHandlerClick = WrappedComponent => props => {

  let { times, setTimes, children, onClick, ..._props } = props;
    
  const handleClick = e => {
    e.preventDefault();
    setTimes( ++times );
    onClick && onClick();
  };

  return (
    <WrappedComponent times={times} handleClick={handleClick} { ..._props }>
      {children}
    </WrappedComponent>
  );

}
```
*withHandlerClick.js*

```jsx
const withDisplayTrack = WrappedComponent => props => {
  const { children, onClick, handleClick, times, ..._props } = props;
  return (
    <span onClick={handleClick}>
      <WrappedComponent
        type={times > 5 ? "danger" : "primary"}
        {..._props}
      >
        {children} <small>({times} times clicked)</small>
      </WrappedComponent>
    </span>
  )
}
```
*withDisplayTrack.js*

With these 3 HOCs we can then apply them to our elements in this way…
```jsx
const ButtonWithTrack = withStateTimes(withHandlerClick(withDisplayTrack(Button)));
```
What’s going on here? Well, withDisplayTrack(Button) returns a component that is used in the call of withHandlerClick that will also return a component that will be used in the call of withStateTimes that will return our final component (ButtonWithTrack).

As you can see, the idea is good because we can reuse our code in this way, but creating these HOCs is a bit complicated and also applying them in this way is a bit hard to read.

Is there any improvement over this?

[**_Recompose_**](https://github.com/acdlite/recompose) to the rescue!! :)

### Recompose

What is _Recompose_?

In their own words:

> [Recompose](https://github.com/acdlite/recompose) is a React utility belt for function components and higher-order components. Think of it like [lodash](https://lodash.com/docs/4.17.10#lodash) for React.

So, it’s a set of methods we can use to improve the organization, creation and application of our HOC’s encouraging the use of functional stateless components combined with the composition of HOC’s.

Let’s start with the most used method of _Recompose_ called compose.

#### [compose](https://github.com/acdlite/recompose/blob/master/docs/API.md#compose)

With compose we can _compose_ multiple higher-order components into a single higher-order component.

In our scenario, with compose we can now express the application of our HOC's like this:
```jsx
import { compose } from "recompose";

...

const ButtonWithTrack = compose(
  withStateTimes,
  withHandlerClick,
  withDisplayTrack
)(Button)
```
*Button.js*

Much cleaner and easy to read, right?

#### [withState](https://github.com/acdlite/recompose/blob/master/docs/API.md#withstate)

Another useful method of _Recompose_ for our scenario is withState.

This method creates a HOC with almost the same behavior we implemented in withStateTimes.js.

- it adds a state property
- it creates a _handler_ to set the value of this state property
- it allow us to set a initial value

So, with _Recompose_, now we can express the same logic like this…
```jsx
...
import { withState } from "recompose";
const withStateTimes = withState('times', 'setTimes', 0)
...
```
*withStateTimes.js*

For real? Yes, for real :)

The utility of _Recompose_ starts to make sense, right?

#### [withHandlers](https://github.com/acdlite/recompose/blob/master/docs/API.md#withhandlers)

Let’s continue improving the code of our scenario. Let’s take the HOC withHandlerClick. To improve the creation of this HOC we can use the method withHandlers of _Recompose_.
```jsx
import { withHandlers } from "recompose";

const withHandlerClick = withHandlers({
  handleClick: props => e => {
    let { times, onClick, setTimes } = props;
    e.preventDefault()
    setTimes( ++times );
    onClick && onClick();
  }
})
```
*withHandlerClick.js*

The method withHandlers takes an object map of handler creators. Each one of the properties of this object passed to withHandlers should be a Higher-Order Function that accepts a set of props and returns a function handler. In this way we can generate a handler that will have access to the props of the component.

#### [setDisplayName](https://github.com/acdlite/recompose/blob/master/docs/API.md#setdisplayname)

In our example, if we debug the code with the [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) the component returned by withDisplayTrack is displayed as Unknown.

To fix this, we can use the setDisplayName of _Recompose_ to export a final HOC that will return a component with the name ComponentWithDisplayTrack.
```jsx
export default compose(
  setDisplayName('ComponentWithDisplayTrack'),
  withDisplayTrack
);
```
#### [lifecycle](https://github.com/acdlite/recompose/blob/master/docs/API.md#lifecycle)

With the method lifecycle we can add lifecycle methods to our functional-syntax components.

In our scenario we could add a different version of Button that display the number of pending messages.

We can create a HOC that returns a different view of our button using a messages props:
```jsx
import React from "react";
import { compose, setDisplayName } from "recompose";

const withDisplayMessages = WrappedComponent => props => {
  const { children, messages, loading, ..._props } = props;
  return (
    <WrappedComponent {..._props}>
      {children}
      {loading ? (
        <span className="fas fa-spinner fa-pulse"> </span>
      ) : (
        <span className="badge badge-light">{messages}</span>
      )}
    </WrappedComponent>
  );
};

export default compose(
  setDisplayName("withDisplayMessages"),
  withDisplayMessages
);
```
*withDisplayMessages.js*

And we can add a componentDidMount lifecycle method to our component that will add:

- a loading state set to true when our _fake request_ starts and set to false when it finishes
- amessages state which value will be updated with the random number returned by our _fake request_

Both loading andmessages states _managed_ here will add one new _prop_ each to the returned component, that will be used to propagate the corresponding values:
```jsx
import { lifecycle } from "recompose";

const getPendingMessages = () => {
  const randomNumber = Math.ceil(Math.random() * 10);
  return new Promise(resolve => {
    setTimeout(() => resolve(randomNumber), randomNumber * 1000);
  });
};

const withDidMountStateMessages = lifecycle({
  componentDidMount() {
    this.setState({ loading: true });
    getPendingMessages().then(messages => {
      this.setState({ loading: false, messages });
    });
  }
});

export default withDidMountStateMessages;
```
*withDidMountStateMessages.js*

With these new HOC’s we can now quickly create our new type of Button :
```jsx
const ButtonWithMessages = compose(
  withDidMountStateMessages, 
  withDisplayMessages
)(Button)
```
#### [defaultProps](https://github.com/acdlite/recompose/blob/master/docs/API.md#defaultprops)

With these HOCs we can transfer these new behaviors into a link with very few lines. And we can add the defaultProps to change the default type of the link.
```jsx
const LinkWithMessages = compose(
  defaultProps({ type: "info" }),
  withDidMountStateMessages,
  withDisplayMessages
)(Link);
```
*Link.js*
### Conclusions

With these methods we can finish our demo by easily creating another version of Button (just to show the flexibility of this pattern) that track the clicks from 3 to zero, and adds another prop so we can change the type when the countdown reach zero.
```jsx
const ButtonWithTrackCountdown = compose(
  withState('times', 'setTimes', 3),
  withState('type', 'setType', 'primary'),
  withHandlers({
    handleClick: props => e => {
      let { times, onClick, setTimes, setType } = props;
      e.preventDefault()
      if ( times <= 0 ) {  setType('secondary') }
      else { setTimes( --times ) }
      onClick && onClick();
    }
  }),
  withDisplayTrack
)(Button)
```
As you can see, with _Recompose_ it is easier to delegate the logic into small Higher-Order Components and then _compose_ them into a more complex HOC that we can use to create different versions of our components reusing most of our code.

Also, _Recompose_ discourage the use of Class syntax for creating components and encourage the use of Functional Stateless Components combined with Higher Components.

The most important advantages of using only Function components are:

- They encourage code that is more reusable and modular.
- They discourage giant, complicated components that do too many things.

Basically, once you get how _Recompose_ methods work, it simplifies the development and organization of React components.

There are a [lot more of methods](https://github.com/acdlite/recompose/blob/master/docs/API.md) that can be used to generate more Higher-Order Components in an easier way.

In the [official repo](https://github.com/acdlite/recompose) you can find some [_Recompose_ recipes](https://github.com/acdlite/recompose/wiki/Recipes) that can be useful to your project.

Also, here you have the code used in this post and a live demo of the result.

{% codesandbox jp392km6vy %}

So, now that you know a bit more about _Recompose_… What is your first impression? Do you think is a good way to go when creating components?

My opinion is… that I like it!! I really like the patterns encouraged by _Recompose_ oriented to the creation of small and simple pieces (components and HOC’s) that can be used to create more complex ones in an easy-to-read way and that are functional-programming oriented.

Well, that’s my opinion. What is yours?
* * *
### Plug: [LogRocket](http://logrocket.com), a DVR for web apps

[![](https://cdn-images-1.medium.com/max/1024/1*s_rMyo6NbrAsP-XtvBaXFg.png)](http://logrocket.com)

[LogRocket](https://logrocket.com) is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single page apps.

Try it for free.
* * *
The post [Using Recompose to write cleaner Higher-Order Components](https://blog.logrocket.com/using-recompose-to-write-clean-higher-order-components-3019a6daf44c/) appeared first on [LogRocket Blog](https://blog.logrocket.com).