To be honest, React’s render props technique didn’t make sense to me until I saw a practical example, so let’s dive in! Or you can TLDR;

The Problem

Let’s say we’re tasked to create button that opens a PayPal window:

So we hop in our editor and make a PayPalLauncher button:

The PayPalLauncher may store an instance of PayPal with some additional lifecycle logic, so it’s great to wrap this logic in a component.

But what if the requirements ask for additional PayPal triggers? For instance:

Now we have two buttons and an orange link that need to open the PayPal window. Let’s look at couple ways to handle this.

Solution 1 — Render logic

Initially, you may be tempted to write some code like this inside PayPalLauncher :

Don’t do this.

Here, we’re passing a prop called type to determine which PayPal trigger to render. This is a lot of logic to express a few visual changes. And this still doesn’t quite give us the flexibility to render any visual component as we please. What if there was a way to separate the logic from the view?

Solution 2— Nesting

Nesting can help us write more expressive JSX:

Now we’ve got some clean separation between the logic ( PayPalLauncher ) and the view ( PayPalButton ). This gives us the flexibility to render any component as our PayPal trigger. And it reads well! But how do we share a prop between PayPalLauncher and PayPalButton ? Let’s see how this looks in PayPalLauncher :

Whoa, what is going on here? We’re cloning the children and passing the prop launchPayPal implicitly to each child. This means that any child you nest in PayPalLauncher must accept the prop launchPayPal . While nesting gives us some pretty expressive JSX, this technique is not super ideal if we are trying to create reusable components with generic interfaces.

Solution 3 — Render Props 🎉

Render props is a technique to pass props from a parent to child using a function or closure. Let’s see what this looks like*:

Instead of treating props.children as nodes, we’re creating a closure and choosing the arguments to expose to the child nodes. In this case, we’re exposing the launchPayPal class instance method.

When we go to implement, our resulting code looks like:

What does this mean? Instead of elements, we pass a function as a child to PayPalLauncher . Because of this, we can easily map launchPayPal to PayPalButton 's onClick handler. Now we have the flexibility to render any component we want and easily map the parent's launchPayPal to any handler on the child.

A Little More Advanced

A surprise benefit of using render props is that it can expose launchPayPal to a parent Page and allows us to add more functionality. For instance, let’s say you want to register the user and validate the form before launching the the PayPal window:

Because launchPayPal is exposed by render props to the parent Page , we can easily add context-specific functionality using functional composition. Here we’re decorating launchPayPal with some Page concerns and using pipe to keep everything super readable 😍.

Recap

What are we gaining with render props?

Reusable logic — by separating view from logic, we don’t have to marry our logic to any one component or visual representation.

Clean and easy to read JSX.

Facilitates component composition and functional composition in your React Apps.

Do you also fret over the composability of your React Apps? We’re hiring!

* Remember that render props is a pattern and can be implemented in number of ways — you should choose what works well with your team.