All Articles

My Favorite Recompose Functions

Recompose is great. Ever used libraries like Lodash or Ramda? Recompose is that, but for React.

This

Becomes this

This style’s really grown on me, and I’d like to share a few of my favorite functions from this awesome utility belt.

withHandlers() and withState()

Let’s say we want to display a user’s name as they type. I’m basing this off the example in the official docs.

Traditionally, our JSX might look like

We need state management to handle the user’s name, so we use this.state.value. Let’s define that state in the constructor and add a handler to update it.

Our state’s initialized to { value: '' } and we’ve added an updateValue method. We’ve already hooked it up in our JSX. Let’s try it out.

Cool, it works. As you type, the username’s updated in real-time.

Here’s a possible Recompose version. Our component will now accept a prop called onChange.

We’ll add state and a handler to update it using withState.

withState accepts three parameters, stateName, stateUpdaterName, and initialState.

In this case we created a piece of state called value, initialized it as an empty string, and made a function to update it called updateValue.

Now for withHandlers.

withHandlers accepts as an object of handlers: higher-order functions that accept props and return a handler. Even after the handler’s returned, it can access its parent function’s props via closure.

updateValue is the updater function provided by withState, and we’re using it inside of withHandlers to set event.target.value as the new state value. All of this happens inside the handler onChange, which will be passed to our component as a prop!

Remember MyForm now calls its onChange prop whenever the user updates the input box.

Our default export now looks like this

After invoking withState and withHandlers, you get back higher-order components. A higher-order component must be invoked with another component.

That’s why we’re passing MyForm to addHandlers, then passing addHandlers(MyForm) to addState. One decorates the next, uniting to form a greater entity.

And our functionality remains unchanged.

compose()

If you’re familiar with functional programming, you likely recognize compose(). If not, I’ve written a post explaining it here.

compose combines n functions, allowing you to more elegantly nest functions. Let’s refactor our enhanced MyForm with it.

We previously had this

We’ll import compose

And use it like so

One pattern I’ve seen in the Recompose docs is storing your “enhancements” in a variable, then exporting that variable + your component. Here’s an example.

I’ve adopted this pattern as it makes a lot of sense to me.

Your component is a pure function that takes props and returns JSX.

Your “enhancements” are higher-order components meant to add or improve upon your component’s functionality.

Defining and combining them in this fashion seems to complement that idea.

I’ll share one more of my favorite higher-order components: lifecycle.

lifecycle

You might guess by the name, lifecycle gives your pure, functional component access to React’s lifecycle hooks, meant strictly for classes.

lifecycle actually uses a class under the hood, but you only deal with functions. And that’s the whole point. Since everything is exposed to you as a function, that’s all you have to think about.

Let’s add it to our enhanceComponent higher-order component. We’ll import it first.

Then put it down below

As you can see, lifecycle takes an object of functions, like withHandlers, but these functions must be named after a valid React lifecycle hook.

We get the following alert on the screen

It’s also preferable to use ES6 method definitions to allow access to this.props. If you want to call a handler from props, you’d need this pointing at the right context.

Let’s say in componentDidMount() we want to set the username to “Lifecycle hook!”

Resulting in this

That won’t work if we use an arrow function

If we console.log(this) we get the following

It works if you use an ES5-style function, though.

Nowadays I shy away from ES5 functions, so method definitions will do just fine.

Other utility functions

These are my go-to Recompose functions.

As I’ve begun using RxJS Observables again, some other Recompose functions have caught my interest.

They might be the subject of a future post, here’s a link to the Recompose observable utils docs if you’re interested.

Until next time!