The concept of children as a function or child as a function , also called render prop in general, is one of the advanced patterns in React (next to higher-order components ). The components which implement this pattern could be called render prop components. In this tutorial, you will learn everything about Reactâs render prop pattern. Along the way, you will implement a currency converter in React, see how the render prop pattern can be compensated with alternative patterns in React too, but then how it can be solved with a render prop component. Afterward, the usage of the render prop pattern should be clear and there shouldnât be any confusion about children as a function, render prop or render prop components left.
Letâs get started with the implementation of the currency converter in order to learn about Reactâs render prop pattern. If you want to follow in your own editor/IDE, you can use create-react-app to get your application up and running. Then the only file you need to touch will be the src/App.js file:
First, letâs implement a new React component next to the App component where you can increment (and decrement) a number. In this case, the abstract number will be the amount of US Dollar which should be converted to other currencies later on:
Thatâs only a simplification of the domain, because, for instance, it would be more convenient having an input field element or only positive numbers for the amount of US Dollars. For the sake of learning about render props, we leave these features out and keep the component simple.
Now letâs tap into the problem space where render props or alternatives can be applied for this scenario: What if you want to use the amount, which is set to the state of the Amount component, in dedicated currency components which apply the exchange rate?
There are a couple of solutions for this problem and we will go through most of them one by one before we end up with Reactâs render props pattern eventually.
The naive approach would be to render the currency components within the Amount component:
Itâs totally valid doing it this way. The major advantage here is the simplicity of it. If there is no strong use case of having more control about what is rendered within the Amount component, you can go for it. However, the disadvantage is that the Amount component has to know about the currency components now. Every time you want to change the rendered output you would have to touch the Amount component. So what if you could just leave the Amount component as it was before and get the currency components outside of it?
Getting the currency components rendered outside of the Amount component isnât too difficult, right? Just render them in the App component instead of the Amount component.
But itâs not that simple, because the currency components donât know about the amount now. You would have to lift the state from the Amount component to the App component.
The App component turned into a stateful class component and the Amount component into a functional stateless component. All state is managed by the App component and the currency components and the Amount component only receive props. The implementation for managing the state was kept the same, it was only lifted up to the App component. So this approach would be a valid solution to the problem.
But wait, what about component composition in React with its children prop? This should work too, shouldnât it? Letâs revert the components to their old implementation and see what this would look like. The Amount component would get control over the amount state again. In addition to the previous version, it would render the children prop for the composition too.
Now the App component could pass the currency components as children prop to the Amount component:
However, again you would have to lift state up to the App component in order to pass the amount to the currency components. As you can see, the component composition on its own doesnât help us to solve the problem. Thatâs the point where Reactâs render props pattern comes into play which enhances Reactâs component composition with an important ingredient: a render function.
The render prop pattern enhances Reactâs patterns for compositions. Instead of passing the currency components as components, you pass them as a function which renders them.
It gives you a way to pass data from the wrapping component (Amount) to its inner composed component(s) (currency components). Because of this function, you can use the children prop within the render prop component (thatâs what the Amount component became by implementing this pattern). The children prop becomes a children as a function.
Rather than using the children directly to render them, you have to call it as function now, because the children are passed as function to the Amount component in the first place. Still you wouldnât have access to the amount in the currency components. However, since you are using children as a function now, you can pass the amount state to the function and access it as argument in the function signature outside of the Amount component.
Thatâs the crucial point for the render prop pattern. In this case, the Amount component became a render prop component , because it implements the render prop pattern , and uses a children as a function or also called child as a function to pass its own state (or other data) to the composed components (here currency components). The currency components are still decoupled from the Amount component and you can even add other components and elements into the composition.
But why is it called render prop? Historically the pattern evolved from using a prop called render (or anything else) for it. Basically the component uses a render prop instead of a children as a function now. But it doesnât have to be the name ârenderâ prop. You can name it however you want:
Thatâs especially useful when combining it with Reactâs slot pattern , which is used for passing multiple composed components to different places within a (render prop) component, but then advancing it with a render prop function to pass the state from the render prop component to the composed components.
In this case, Reactâs slot pattern got extended with the function which makes the data from within the render prop component accessible to the slotted components again. As you can see, combining all the (advanced) patterns in React gives you fine-grained control over your component composition.
For the sake of completeness, the following code demonstrates that the problem could be solved with a higher-order component (HOC) as well:
Then it could be used by passing an array of currency components to the HOC:
And finally using it in your App component:
However, in this case you would lose the possibility to render something in between. You are strictly coupled to the higher-order componentâs render method. If you need to add something in between the currency components, you would have to do it in the higher-order component. It would be quite familiar as you have done it previously by rendering the currency components straight away in the Amount component. If you are using a render prop component instead, you would be flexible in your composition. Thatâs only one different aspect of render prop components and higher-order components.
You can find the final render prop componentâs implementation in this GitHub repository . The render prop component in React, which can be implemented with a render prop as function or children as a function approach, is an advanced pattern in React. It is used to expose internal data from within a render prop component for making it accessible to other components within the render prop componentâs composition. If you want to dig deeper into render prop components, checkout this article about using render props for making stateless components stateful .
Another advanced pattern in React are higher-order components which are used as well to abstract functionality away from your components but not in such a dynamic way. However, you have also seen that problems which are solved by renders props can be solved by other patterns (e.g. simply rendering the component within or lifting state) too. Last but not least, the article should have shed some light into the terminology of the render prop pattern/components, children as a function and render prop itself.