Render Props in React

Jun 2, 2018 · 4 min read


First, what is a render prop (RP)?

A RP is simply a prop that takes a function which returns elements that will be used in .

You can pass an element directly into a prop and use it in which would make the whole thing a RP by name, but generally, when people speak about RPs, they mean the first definition.

Also, since the of a component are also a prop, you can use them instead of other/named props, which is also called function as children.

const C = props => props.renderProp();
// or
const C = props => props.children();


To get the why of RPs, we first have to do a step back.

In the last years it became common practice in React to use dependency injection to create nested elements, RPs are a natural extension of that principle.

Dependency Injection (DI): The basic idea is, you remove hard-coded identifier from your code. For example, a function could use another function to do something, but it could also get a function reference passed into it that does something.

Here an example, a function that creates a string with a random value. The first version uses directly, the second one doesn’t know anything about it and could use a completly different source for its random value.

// Non-DI
const f = () => "The value is: " + Math.random();
// Usage
// DI
const f = g => "The value is: " + g();
// Usage

How does this translate to React?

A common problem in graphical user interfaces are lists of multiple items. You often have a bunch of items, list them and suddendly you need an item of a different type in that same list.

If you implement it naively you could end up with something like that:

const List = props => (
{ => <ListItem text={i}/>)}
const ListItem = props => <li>{props.text}</li>;
// Usage
<List data={["Hello", "World"]}/>

But now your needs to know about so when you want to add something like you would have to change the . While this isn’t a big problem in such a small example, it could get more complicated with others, like when you don’t implemented the and now need to ask some other developer to do it for you.

The DI way to do it could look like that:

const List = props => <ul>{props.children}</ul>;
const ListItem = props => <li>{props.text}</li>;
const HeaderListItem = props => (
<li style={{background: "red"}}>
// Usage
<HeaderListItem text="Header!"/>
{ => <ListItem text={i}/>)}

As you can see, the doesn’t know anything about or it just renders its . Which requires a bit more typing at the call-site, but makes the component much more flexible and less opinionated.

Now that we understand how DI leads to more flexible code, what does this has to do with RPs?

RPs are like a natural extension of that principle to logic. While the DI example I showed you worked rather nice for flexible element composition, RPs allow you to use this to encapsule other kind of logic, so it can be used with different components.


Like I already told you, RPs are simply props of a component you can pass functions into. These functions have to return elements, which will be used in that components rendering.

A simple example could be a component, that delivers a random number to its RP.

const Random = props => props.render(Math.random());
const Text = props => <p>{props.children}</p>;
// Usage
<Random render={number => <Text>{number}</Text>}/>

In this example is still hard-coded (non-DI, for brevity sake), but the element is injected and gets passed the random value via the function it’s wrapped with. The wrapping function prevents the creation of the element till it’s called by and allows some logic to happen before it’s called.

Now every component can be wrapped with and since the values are passed into the function as arguments and not directly into a specific prop, you can decide at call time what argument you want to pass into which prop of the injected component.

Comparison with Higher Order Components

For a long time higher order components (HoC) were the way to share logic in React, so why did this change?

First, lets see how the Random example would look like with a HoC.

const withRandom = (Wrapped, targetProp) =>
class Random extends React.Component {
render() {
return <Wrapped {...{[targetProp]: Math.random()}} />;
const Text = props => <p>{props.children}</p>;
// Usage
const RandomText = withRandom(Text, "children");

As you can see, this creates a wrapped version of at definition time and not at render time. While this is a form composition, which is favored over inheritence, it forces you to create a new component every time you want to wrap something, also it’s less flexible in terms of props, since they would also have to be defined at wrapping time.

With RPs wrapping and usage time are the same, so you can do all in one go.


RPs can be used to add flexibility into your app, making it much more resilient to change.

You can add new elements into the RP to simply change what is displayed, for example change tables to Graphs etc.

You can also change the wrapping RP component to let the children rceive data from a different source, but you wouldn’t have to change the children, because you could map the data from the RP arguments to the right child-props on-the-fly.

This article was originally published on

Byteconf React is a free React/JavaScript conference, streamed on Twitch. Join us on August 31, 2018, to hear from the best React developers and teachers from around the world. Join our mailing list and follow us on Twitter to stay up to date!

Bytesized Code

We make developer conferences for everyone, and publish the…