Render Props, Render Callbacks And Higher-Order Components Are All Interchangeable

Making rendering patterns interchangeable

A. Sharif
JavaScript Inside
4 min readJun 12, 2018

--

Introduction

There has been a lot of discussion around concepts like render-props, render-callbacks and higher-order components in the React community. Most commonly mixins where used to enhance a React Component with additional functionality like managing state f.e. After React moved from createClass to ES6 classes, higher-order components became the favoured why to enhance components, but also the render callback pattern was in use, f.e. react-motion leverages children props to pass additional props and functionalities. A less common pattern was to use a so called render prop, so instead of the above mentioned approaches, you define a prop which accepts a callback. Michael Jackson’s “Use a Render Prop!” made this pattern very popular.

Basics

All three mentioned patterns solve the same thing that mixins used to solve. Before we continue, let’s look at a couple of practical examples.

Render Prop

First, let’s build a small component that keeps track of our count state and renders any callback we pass to our render prop.

Take a look at the following example:

In our CounterComponent render function we merge props, state and add an update function and pass it to the render prop.

Next, we will need a component that renders anything valuable to the screen.

Our Counter component accepts a count and an update function and displays an increment and decrement button as well as the current count.

Finally we can use our CounterComponent to enhance the Counter with the additional functionality.

Higher-Order Components

Now that we covered render props, let’s take a look at how we would construct a higher-order component that offers the exact same functionality.

Looking at the above the example, we can see that we need to pass in our to be rendered Component to receive a brand new Component with the enhanced functionalities and props.

We should have covered the basic concepts now. Knowing that we can use different patterns to achieve the same results, we will focus on making theses concepts interchangeable.

Transforming between render props and higher-order components

Sometimes you might have a library that offers a higher-order-component but your favoured way of composing components is via JSX. Sometimes you might have a library that offers a render-prop, but you would like to compose multiple enhancing components via a compose function f.e. The interesting thing is that these concepts are interchangeable.

Let’s build on our previous examples and add transformation functions that would take a higher-order component and return a render-prop and vice versa.

The toHoc functionality can be summed as:

Also check ”Use a Render Prop!” for an alternative implementation.

This converts a render prop to a higher order component.

Let’s verify this behaviour.

Converting from a higher-order component to a render-prop is slightly more complicated. We need to pass in a component with a render prop to the actual higher-order-component. All credits to Brent Jackson, (see this implemented in refunk).

Alternatively, this can also be accomplished without using a class baed approach. All credits to Rodrigo Pombo (also check this example).

Again, we can verify that this works as expected.

We can build a small helper that converts back and forth between higher-order-components and render-props. Check the following example. It should also be noted that we can initiate the toHoc with an additional render name, as the rendering prop might have a different name or be a child prop.

Finally, let’s see the different concepts back to back.

Summary

Render props, render callbacks and higher-order component are interchangeable. For most cases render props will suffice, but you can transform back between these patterns in user land if needed.

Very special thanks to Brent Jackson Kent C. Dodds and Rodrigo Pombo for sorting out problems with the fromHoc implementation.

Links

Use a Render Prop!: render prop pattern explained by Michael Jackson

React Patterns: excellent collection of React patterns by michael chan

Higher-Order Components: Official React Docs

Render Props: Official React Docs

Downshift: Example of using a render prop via Downshift by Kent C. Dodds

Refunk: Example of converting a higher-order component to render prop by Brent Jackson

If there are better ways to solve these problems or if you have any questions, please leave a comment here or on Twitter.

--

--

A. Sharif
JavaScript Inside

Focusing on quality. Software Development. Product Management.